t_ptrace_wait.c revision 1.128
11.128Skamil/* $NetBSD: t_ptrace_wait.c,v 1.128 2019/06/18 21:14:26 kamil Exp $ */ 21.1Skamil 31.1Skamil/*- 41.78Skamil * Copyright (c) 2016, 2017, 2018, 2019 The NetBSD Foundation, Inc. 51.1Skamil * All rights reserved. 61.1Skamil * 71.1Skamil * Redistribution and use in source and binary forms, with or without 81.1Skamil * modification, are permitted provided that the following conditions 91.1Skamil * are met: 101.1Skamil * 1. Redistributions of source code must retain the above copyright 111.1Skamil * notice, this list of conditions and the following disclaimer. 121.1Skamil * 2. Redistributions in binary form must reproduce the above copyright 131.1Skamil * notice, this list of conditions and the following disclaimer in the 141.1Skamil * documentation and/or other materials provided with the distribution. 151.1Skamil * 161.1Skamil * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 171.1Skamil * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 181.1Skamil * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 191.1Skamil * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 201.1Skamil * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 211.1Skamil * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 221.1Skamil * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 231.1Skamil * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 241.1Skamil * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 251.1Skamil * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 261.1Skamil * POSSIBILITY OF SUCH DAMAGE. 271.1Skamil */ 281.1Skamil 291.1Skamil#include <sys/cdefs.h> 301.128Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.128 2019/06/18 21:14:26 kamil 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.1Skamil#include <sys/wait.h> 411.1Skamil#include <machine/reg.h> 421.1Skamil#include <elf.h> 431.1Skamil#include <err.h> 441.1Skamil#include <errno.h> 451.1Skamil#include <lwp.h> 461.77Skamil#include <pthread.h> 471.1Skamil#include <sched.h> 481.1Skamil#include <signal.h> 491.124Skamil#include <spawn.h> 501.1Skamil#include <stdint.h> 511.1Skamil#include <stdio.h> 521.1Skamil#include <stdlib.h> 531.1Skamil#include <strings.h> 541.26Skamil#include <time.h> 551.1Skamil#include <unistd.h> 561.1Skamil 571.114Skamil#include <fenv.h> 581.114Skamil#if (__arm__ && !__SOFTFP__) || __aarch64__ 591.114Skamil#include <ieeefp.h> /* only need for ARM Cortex/Neon hack */ 601.114Skamil#endif 611.114Skamil 621.121Smgorny#if defined(__i386__) || defined(__x86_64__) 631.121Smgorny#include <cpuid.h> 641.121Smgorny#include <x86/cpu_extended_state.h> 651.121Smgorny#endif 661.121Smgorny 671.1Skamil#include <atf-c.h> 681.1Skamil 691.1Skamil#include "h_macros.h" 701.1Skamil 711.1Skamil#include "t_ptrace_wait.h" 721.1Skamil#include "msg.h" 731.1Skamil 741.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \ 751.61Skre SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \ 761.61Skre sizeof(msg)) == 0) 771.1Skamil 781.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \ 791.61Skre FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \ 801.61Skre sizeof(msg)) == 0) 811.1Skamil 821.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \ 831.61Skre FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \ 841.61Skre sizeof(msg)) == 0) 851.1Skamil 861.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \ 871.61Skre SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \ 881.61Skre sizeof(msg)) == 0) 891.13Schristos 901.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \ 911.13Schristos strerror(errno)) 921.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \ 931.18Schristos "%d(%s) != %d", res, strerror(res), exp) 941.13Schristos 951.13Schristosstatic int debug = 0; 961.13Schristos 971.13Schristos#define DPRINTF(a, ...) do \ 981.123Skamil if (debug) \ 991.123Skamil printf("%s() %s:%d " a, __func__, __FILE__, __LINE__, ##__VA_ARGS__); \ 1001.13Schristos while (/*CONSTCOND*/0) 1011.1Skamil 1021.110Skamil#ifndef TEST_VFORK_ENABLED 1031.127Skamil#define TEST_VFORK_ENABLED 1 1041.110Skamil#endif 1051.109Skamil 1061.128Skamil#ifndef TEST_LWP_ENABLED 1071.128Skamil#define TEST_LWP_ENABLED 0 1081.128Skamil#endif 1091.128Skamil 1101.34Skamil/// ---------------------------------------------------------------------------- 1111.34Skamil 1121.33Skamilstatic void 1131.33Skamiltraceme_raise(int sigval) 1141.1Skamil{ 1151.1Skamil const int exitval = 5; 1161.1Skamil pid_t child, wpid; 1171.1Skamil#if defined(TWAIT_HAVE_STATUS) 1181.1Skamil int status; 1191.1Skamil#endif 1201.1Skamil 1211.45Skamil struct ptrace_siginfo info; 1221.45Skamil memset(&info, 0, sizeof(info)); 1231.45Skamil 1241.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 1251.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 1261.1Skamil if (child == 0) { 1271.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1281.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1291.1Skamil 1301.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1311.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 1321.1Skamil 1331.36Skamil switch (sigval) { 1341.36Skamil case SIGKILL: 1351.36Skamil /* NOTREACHED */ 1361.36Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 1371.70Smrg __unreachable(); 1381.36Skamil default: 1391.36Skamil DPRINTF("Before exiting of the child process\n"); 1401.36Skamil _exit(exitval); 1411.36Skamil } 1421.1Skamil } 1431.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1441.1Skamil 1451.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1461.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1471.1Skamil 1481.36Skamil switch (sigval) { 1491.36Skamil case SIGKILL: 1501.36Skamil validate_status_signaled(status, sigval, 0); 1511.36Skamil break; 1521.36Skamil default: 1531.36Skamil validate_status_stopped(status, sigval); 1541.1Skamil 1551.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 1561.61Skre "child\n"); 1571.45Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 1581.61Skre sizeof(info)) != -1); 1591.45Skamil 1601.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1611.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 1621.61Skre "si_errno=%#x\n", 1631.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1641.61Skre info.psi_siginfo.si_errno); 1651.45Skamil 1661.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 1671.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 1681.45Skamil 1691.36Skamil DPRINTF("Before resuming the child process where it left off " 1701.36Skamil "and without signal to be sent\n"); 1711.36Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1721.1Skamil 1731.36Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1741.36Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 1751.61Skre child); 1761.36Skamil break; 1771.36Skamil } 1781.1Skamil 1791.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1801.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 1811.1Skamil} 1821.1Skamil 1831.61Skre#define TRACEME_RAISE(test, sig) \ 1841.61SkreATF_TC(test); \ 1851.61SkreATF_TC_HEAD(test, tc) \ 1861.61Skre{ \ 1871.61Skre atf_tc_set_md_var(tc, "descr", \ 1881.61Skre "Verify " #sig " followed by _exit(2) in a child"); \ 1891.61Skre} \ 1901.61Skre \ 1911.61SkreATF_TC_BODY(test, tc) \ 1921.61Skre{ \ 1931.61Skre \ 1941.61Skre traceme_raise(sig); \ 1951.33Skamil} 1961.33Skamil 1971.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */ 1981.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */ 1991.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */ 2001.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP) /* hangup */ 2011.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */ 2021.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */ 2031.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */ 2041.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */ 2051.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */ 2061.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */ 2071.33Skamil 2081.34Skamil/// ---------------------------------------------------------------------------- 2091.1Skamil 2101.1Skamilstatic void 2111.87Skamiltraceme_raisesignal_ignored(int sigignored) 2121.87Skamil{ 2131.87Skamil const int exitval = 5; 2141.87Skamil const int sigval = SIGSTOP; 2151.87Skamil pid_t child, wpid; 2161.87Skamil struct sigaction sa; 2171.87Skamil#if defined(TWAIT_HAVE_STATUS) 2181.87Skamil int status; 2191.87Skamil#endif 2201.87Skamil struct ptrace_siginfo info; 2211.87Skamil 2221.87Skamil memset(&info, 0, sizeof(info)); 2231.87Skamil 2241.87Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 2251.87Skamil SYSCALL_REQUIRE((child = fork()) != -1); 2261.87Skamil if (child == 0) { 2271.87Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2281.87Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2291.87Skamil 2301.87Skamil memset(&sa, 0, sizeof(sa)); 2311.87Skamil sa.sa_handler = SIG_IGN; 2321.87Skamil sigemptyset(&sa.sa_mask); 2331.87Skamil FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1); 2341.87Skamil 2351.87Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 2361.87Skamil FORKEE_ASSERT(raise(sigval) == 0); 2371.87Skamil 2381.87Skamil DPRINTF("Before raising %s from child\n", 2391.87Skamil strsignal(sigignored)); 2401.87Skamil FORKEE_ASSERT(raise(sigignored) == 0); 2411.87Skamil 2421.87Skamil DPRINTF("Before exiting of the child process\n"); 2431.87Skamil _exit(exitval); 2441.87Skamil } 2451.87Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2461.87Skamil 2471.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2481.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2491.87Skamil 2501.87Skamil validate_status_stopped(status, sigval); 2511.87Skamil 2521.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2531.87Skamil SYSCALL_REQUIRE( 2541.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2551.87Skamil 2561.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2571.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2581.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2591.87Skamil info.psi_siginfo.si_errno); 2601.87Skamil 2611.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 2621.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2631.87Skamil 2641.87Skamil DPRINTF("Before resuming the child process where it left off and " 2651.87Skamil "without signal to be sent\n"); 2661.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2671.87Skamil 2681.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2691.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2701.87Skamil 2711.87Skamil validate_status_stopped(status, sigignored); 2721.87Skamil 2731.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2741.87Skamil SYSCALL_REQUIRE( 2751.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2761.87Skamil 2771.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2781.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2791.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2801.87Skamil info.psi_siginfo.si_errno); 2811.87Skamil 2821.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored); 2831.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2841.87Skamil 2851.87Skamil DPRINTF("Before resuming the child process where it left off and " 2861.87Skamil "without signal to be sent\n"); 2871.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2881.87Skamil 2891.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2901.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2911.87Skamil 2921.87Skamil validate_status_exited(status, exitval); 2931.87Skamil 2941.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2951.87Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 2961.87Skamil} 2971.87Skamil 2981.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig) \ 2991.87SkamilATF_TC(test); \ 3001.87SkamilATF_TC_HEAD(test, tc) \ 3011.87Skamil{ \ 3021.87Skamil atf_tc_set_md_var(tc, "descr", \ 3031.87Skamil "Verify that ignoring (with SIG_IGN) " #sig " in tracee " \ 3041.87Skamil "does not stop tracer from catching this raised signal"); \ 3051.87Skamil} \ 3061.87Skamil \ 3071.87SkamilATF_TC_BODY(test, tc) \ 3081.87Skamil{ \ 3091.87Skamil \ 3101.87Skamil traceme_raisesignal_ignored(sig); \ 3111.87Skamil} 3121.87Skamil 3131.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 3141.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */ 3151.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP) /* hangup */ 3161.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */ 3171.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */ 3181.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */ 3191.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */ 3201.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */ 3211.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */ 3221.87Skamil 3231.87Skamil/// ---------------------------------------------------------------------------- 3241.87Skamil 3251.87Skamilstatic void 3261.86Skamiltraceme_raisesignal_masked(int sigmasked) 3271.86Skamil{ 3281.86Skamil const int exitval = 5; 3291.86Skamil const int sigval = SIGSTOP; 3301.86Skamil pid_t child, wpid; 3311.86Skamil#if defined(TWAIT_HAVE_STATUS) 3321.86Skamil int status; 3331.86Skamil#endif 3341.86Skamil sigset_t intmask; 3351.86Skamil struct ptrace_siginfo info; 3361.86Skamil 3371.86Skamil memset(&info, 0, sizeof(info)); 3381.86Skamil 3391.86Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 3401.86Skamil SYSCALL_REQUIRE((child = fork()) != -1); 3411.86Skamil if (child == 0) { 3421.86Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 3431.86Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 3441.86Skamil 3451.86Skamil sigemptyset(&intmask); 3461.86Skamil sigaddset(&intmask, sigmasked); 3471.86Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 3481.86Skamil 3491.86Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 3501.86Skamil FORKEE_ASSERT(raise(sigval) == 0); 3511.86Skamil 3521.86Skamil DPRINTF("Before raising %s breakpoint from child\n", 3531.86Skamil strsignal(sigmasked)); 3541.86Skamil FORKEE_ASSERT(raise(sigmasked) == 0); 3551.86Skamil 3561.86Skamil DPRINTF("Before exiting of the child process\n"); 3571.86Skamil _exit(exitval); 3581.86Skamil } 3591.86Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 3601.86Skamil 3611.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3621.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3631.86Skamil 3641.86Skamil validate_status_stopped(status, sigval); 3651.86Skamil 3661.86Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 3671.86Skamil SYSCALL_REQUIRE( 3681.86Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 3691.86Skamil 3701.86Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 3711.86Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 3721.86Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 3731.86Skamil info.psi_siginfo.si_errno); 3741.86Skamil 3751.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 3761.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 3771.86Skamil 3781.86Skamil DPRINTF("Before resuming the child process where it left off and " 3791.86Skamil "without signal to be sent\n"); 3801.86Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 3811.86Skamil 3821.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3831.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3841.86Skamil 3851.86Skamil validate_status_exited(status, exitval); 3861.86Skamil 3871.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3881.86Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 3891.86Skamil} 3901.86Skamil 3911.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig) \ 3921.86SkamilATF_TC(test); \ 3931.86SkamilATF_TC_HEAD(test, tc) \ 3941.86Skamil{ \ 3951.86Skamil atf_tc_set_md_var(tc, "descr", \ 3961.86Skamil "Verify that masking (with SIG_BLOCK) " #sig " in tracee " \ 3971.86Skamil "stops tracer from catching this raised signal"); \ 3981.86Skamil} \ 3991.86Skamil \ 4001.86SkamilATF_TC_BODY(test, tc) \ 4011.86Skamil{ \ 4021.86Skamil \ 4031.86Skamil traceme_raisesignal_masked(sig); \ 4041.86Skamil} 4051.86Skamil 4061.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 4071.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */ 4081.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP) /* hangup */ 4091.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */ 4101.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */ 4111.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */ 4121.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */ 4131.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */ 4141.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */ 4151.86Skamil 4161.86Skamil/// ---------------------------------------------------------------------------- 4171.86Skamil 4181.86Skamilstatic void 4191.59Skamiltraceme_crash(int sig) 4201.59Skamil{ 4211.59Skamil pid_t child, wpid; 4221.59Skamil#if defined(TWAIT_HAVE_STATUS) 4231.59Skamil int status; 4241.59Skamil#endif 4251.59Skamil struct ptrace_siginfo info; 4261.61Skre 4271.71Skamil#ifndef PTRACE_ILLEGAL_ASM 4281.71Skamil if (sig == SIGILL) 4291.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 4301.71Skamil#endif 4311.71Skamil 4321.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 4331.114Skamil atf_tc_skip("FP exceptions are not supported"); 4341.114Skamil 4351.59Skamil memset(&info, 0, sizeof(info)); 4361.59Skamil 4371.59Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 4381.59Skamil SYSCALL_REQUIRE((child = fork()) != -1); 4391.59Skamil if (child == 0) { 4401.59Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 4411.59Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 4421.59Skamil 4431.59Skamil DPRINTF("Before executing a trap\n"); 4441.59Skamil switch (sig) { 4451.59Skamil case SIGTRAP: 4461.59Skamil trigger_trap(); 4471.59Skamil break; 4481.59Skamil case SIGSEGV: 4491.59Skamil trigger_segv(); 4501.59Skamil break; 4511.59Skamil case SIGILL: 4521.59Skamil trigger_ill(); 4531.59Skamil break; 4541.59Skamil case SIGFPE: 4551.59Skamil trigger_fpe(); 4561.59Skamil break; 4571.59Skamil case SIGBUS: 4581.59Skamil trigger_bus(); 4591.59Skamil break; 4601.59Skamil default: 4611.59Skamil /* NOTREACHED */ 4621.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4631.59Skamil } 4641.59Skamil 4651.59Skamil /* NOTREACHED */ 4661.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4671.59Skamil } 4681.59Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 4691.59Skamil 4701.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4711.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4721.59Skamil 4731.59Skamil validate_status_stopped(status, sig); 4741.59Skamil 4751.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 4761.61Skre SYSCALL_REQUIRE( 4771.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 4781.59Skamil 4791.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 4801.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 4811.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 4821.61Skre info.psi_siginfo.si_errno); 4831.59Skamil 4841.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 4851.59Skamil switch (sig) { 4861.59Skamil case SIGTRAP: 4871.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 4881.59Skamil break; 4891.59Skamil case SIGSEGV: 4901.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 4911.59Skamil break; 4921.71Skamil case SIGILL: 4931.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 4941.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 4951.71Skamil break; 4961.59Skamil case SIGFPE: 4971.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 4981.59Skamil break; 4991.59Skamil case SIGBUS: 5001.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 5011.59Skamil break; 5021.59Skamil } 5031.59Skamil 5041.59Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 5051.59Skamil 5061.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5071.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 5081.59Skamil 5091.59Skamil validate_status_signaled(status, SIGKILL, 0); 5101.59Skamil 5111.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5121.59Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 5131.59Skamil} 5141.59Skamil 5151.61Skre#define TRACEME_CRASH(test, sig) \ 5161.61SkreATF_TC(test); \ 5171.61SkreATF_TC_HEAD(test, tc) \ 5181.61Skre{ \ 5191.61Skre atf_tc_set_md_var(tc, "descr", \ 5201.61Skre "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \ 5211.61Skre} \ 5221.61Skre \ 5231.61SkreATF_TC_BODY(test, tc) \ 5241.61Skre{ \ 5251.61Skre \ 5261.61Skre traceme_crash(sig); \ 5271.59Skamil} 5281.59Skamil 5291.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP) 5301.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV) 5311.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL) 5321.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE) 5331.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS) 5341.59Skamil 5351.59Skamil/// ---------------------------------------------------------------------------- 5361.59Skamil 5371.59Skamilstatic void 5381.88Skamiltraceme_signalmasked_crash(int sig) 5391.88Skamil{ 5401.89Skamil const int sigval = SIGSTOP; 5411.88Skamil pid_t child, wpid; 5421.88Skamil#if defined(TWAIT_HAVE_STATUS) 5431.88Skamil int status; 5441.88Skamil#endif 5451.88Skamil struct ptrace_siginfo info; 5461.88Skamil sigset_t intmask; 5471.89Skamil struct kinfo_proc2 kp; 5481.89Skamil size_t len = sizeof(kp); 5491.89Skamil 5501.89Skamil int name[6]; 5511.89Skamil const size_t namelen = __arraycount(name); 5521.89Skamil ki_sigset_t kp_sigmask; 5531.88Skamil 5541.88Skamil#ifndef PTRACE_ILLEGAL_ASM 5551.88Skamil if (sig == SIGILL) 5561.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 5571.88Skamil#endif 5581.88Skamil 5591.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 5601.114Skamil atf_tc_skip("FP exceptions are not supported"); 5611.114Skamil 5621.88Skamil memset(&info, 0, sizeof(info)); 5631.88Skamil 5641.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 5651.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 5661.88Skamil if (child == 0) { 5671.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 5681.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 5691.88Skamil 5701.88Skamil sigemptyset(&intmask); 5711.88Skamil sigaddset(&intmask, sig); 5721.88Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 5731.88Skamil 5741.89Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 5751.89Skamil FORKEE_ASSERT(raise(sigval) == 0); 5761.89Skamil 5771.88Skamil DPRINTF("Before executing a trap\n"); 5781.88Skamil switch (sig) { 5791.88Skamil case SIGTRAP: 5801.88Skamil trigger_trap(); 5811.88Skamil break; 5821.88Skamil case SIGSEGV: 5831.88Skamil trigger_segv(); 5841.88Skamil break; 5851.88Skamil case SIGILL: 5861.88Skamil trigger_ill(); 5871.88Skamil break; 5881.88Skamil case SIGFPE: 5891.88Skamil trigger_fpe(); 5901.88Skamil break; 5911.88Skamil case SIGBUS: 5921.88Skamil trigger_bus(); 5931.88Skamil break; 5941.88Skamil default: 5951.88Skamil /* NOTREACHED */ 5961.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 5971.88Skamil } 5981.88Skamil 5991.88Skamil /* NOTREACHED */ 6001.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 6011.88Skamil } 6021.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 6031.88Skamil 6041.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6051.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6061.88Skamil 6071.89Skamil validate_status_stopped(status, sigval); 6081.89Skamil 6091.89Skamil name[0] = CTL_KERN, 6101.89Skamil name[1] = KERN_PROC2, 6111.89Skamil name[2] = KERN_PROC_PID; 6121.89Skamil name[3] = child; 6131.89Skamil name[4] = sizeof(kp); 6141.89Skamil name[5] = 1; 6151.89Skamil 6161.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6171.89Skamil 6181.89Skamil kp_sigmask = kp.p_sigmask; 6191.89Skamil 6201.89Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 6211.89Skamil SYSCALL_REQUIRE( 6221.89Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6231.89Skamil 6241.89Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6251.89Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6261.89Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6271.89Skamil info.psi_siginfo.si_errno); 6281.89Skamil 6291.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 6301.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 6311.89Skamil 6321.89Skamil DPRINTF("Before resuming the child process where it left off and " 6331.89Skamil "without signal to be sent\n"); 6341.89Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 6351.89Skamil 6361.89Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6371.89Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6381.89Skamil 6391.88Skamil validate_status_stopped(status, sig); 6401.88Skamil 6411.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 6421.88Skamil SYSCALL_REQUIRE( 6431.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6441.88Skamil 6451.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6461.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6471.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6481.88Skamil info.psi_siginfo.si_errno); 6491.88Skamil 6501.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6511.89Skamil 6521.89Skamil DPRINTF("kp_sigmask=" 6531.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6541.89Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2], 6551.89Skamil kp_sigmask.__bits[3]); 6561.89Skamil 6571.89Skamil DPRINTF("kp.p_sigmask=" 6581.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6591.89Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 6601.89Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 6611.89Skamil 6621.89Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask))); 6631.89Skamil 6641.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 6651.88Skamil switch (sig) { 6661.88Skamil case SIGTRAP: 6671.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 6681.88Skamil break; 6691.88Skamil case SIGSEGV: 6701.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 6711.88Skamil break; 6721.88Skamil case SIGILL: 6731.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 6741.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 6751.88Skamil break; 6761.88Skamil case SIGFPE: 6771.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 6781.88Skamil break; 6791.88Skamil case SIGBUS: 6801.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 6811.88Skamil break; 6821.88Skamil } 6831.88Skamil 6841.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 6851.88Skamil 6861.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6871.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6881.88Skamil 6891.88Skamil validate_status_signaled(status, SIGKILL, 0); 6901.88Skamil 6911.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6921.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 6931.88Skamil} 6941.88Skamil 6951.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig) \ 6961.88SkamilATF_TC(test); \ 6971.88SkamilATF_TC_HEAD(test, tc) \ 6981.88Skamil{ \ 6991.88Skamil atf_tc_set_md_var(tc, "descr", \ 7001.88Skamil "Verify masked crash signal " #sig " in a child after " \ 7011.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 7021.88Skamil} \ 7031.88Skamil \ 7041.88SkamilATF_TC_BODY(test, tc) \ 7051.88Skamil{ \ 7061.88Skamil \ 7071.88Skamil traceme_signalmasked_crash(sig); \ 7081.88Skamil} 7091.88Skamil 7101.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP) 7111.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV) 7121.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL) 7131.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE) 7141.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS) 7151.88Skamil 7161.88Skamil/// ---------------------------------------------------------------------------- 7171.88Skamil 7181.88Skamilstatic void 7191.88Skamiltraceme_signalignored_crash(int sig) 7201.88Skamil{ 7211.90Skamil const int sigval = SIGSTOP; 7221.88Skamil pid_t child, wpid; 7231.88Skamil#if defined(TWAIT_HAVE_STATUS) 7241.88Skamil int status; 7251.88Skamil#endif 7261.88Skamil struct sigaction sa; 7271.88Skamil struct ptrace_siginfo info; 7281.90Skamil struct kinfo_proc2 kp; 7291.90Skamil size_t len = sizeof(kp); 7301.90Skamil 7311.90Skamil int name[6]; 7321.90Skamil const size_t namelen = __arraycount(name); 7331.90Skamil ki_sigset_t kp_sigignore; 7341.88Skamil 7351.88Skamil#ifndef PTRACE_ILLEGAL_ASM 7361.88Skamil if (sig == SIGILL) 7371.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 7381.88Skamil#endif 7391.88Skamil 7401.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 7411.114Skamil atf_tc_skip("FP exceptions are not supported"); 7421.114Skamil 7431.88Skamil memset(&info, 0, sizeof(info)); 7441.88Skamil 7451.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 7461.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 7471.88Skamil if (child == 0) { 7481.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 7491.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 7501.88Skamil 7511.88Skamil memset(&sa, 0, sizeof(sa)); 7521.88Skamil sa.sa_handler = SIG_IGN; 7531.88Skamil sigemptyset(&sa.sa_mask); 7541.88Skamil 7551.88Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 7561.88Skamil 7571.90Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 7581.90Skamil FORKEE_ASSERT(raise(sigval) == 0); 7591.90Skamil 7601.88Skamil DPRINTF("Before executing a trap\n"); 7611.88Skamil switch (sig) { 7621.88Skamil case SIGTRAP: 7631.88Skamil trigger_trap(); 7641.88Skamil break; 7651.88Skamil case SIGSEGV: 7661.88Skamil trigger_segv(); 7671.88Skamil break; 7681.88Skamil case SIGILL: 7691.88Skamil trigger_ill(); 7701.88Skamil break; 7711.88Skamil case SIGFPE: 7721.88Skamil trigger_fpe(); 7731.88Skamil break; 7741.88Skamil case SIGBUS: 7751.88Skamil trigger_bus(); 7761.88Skamil break; 7771.88Skamil default: 7781.88Skamil /* NOTREACHED */ 7791.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7801.88Skamil } 7811.88Skamil 7821.88Skamil /* NOTREACHED */ 7831.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7841.88Skamil } 7851.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 7861.88Skamil 7871.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7881.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 7891.88Skamil 7901.90Skamil validate_status_stopped(status, sigval); 7911.90Skamil 7921.90Skamil name[0] = CTL_KERN, 7931.90Skamil name[1] = KERN_PROC2, 7941.90Skamil name[2] = KERN_PROC_PID; 7951.90Skamil name[3] = child; 7961.90Skamil name[4] = sizeof(kp); 7971.90Skamil name[5] = 1; 7981.90Skamil 7991.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8001.90Skamil 8011.90Skamil kp_sigignore = kp.p_sigignore; 8021.90Skamil 8031.90Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 8041.90Skamil SYSCALL_REQUIRE( 8051.90Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8061.90Skamil 8071.90Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8081.90Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8091.90Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8101.90Skamil info.psi_siginfo.si_errno); 8111.90Skamil 8121.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 8131.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 8141.90Skamil 8151.90Skamil DPRINTF("Before resuming the child process where it left off and " 8161.90Skamil "without signal to be sent\n"); 8171.90Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 8181.90Skamil 8191.90Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8201.90Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8211.90Skamil 8221.88Skamil validate_status_stopped(status, sig); 8231.88Skamil 8241.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 8251.88Skamil SYSCALL_REQUIRE( 8261.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8271.88Skamil 8281.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8291.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8301.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8311.88Skamil info.psi_siginfo.si_errno); 8321.88Skamil 8331.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8341.90Skamil 8351.90Skamil DPRINTF("kp_sigignore=" 8361.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8371.90Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 8381.90Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 8391.90Skamil 8401.90Skamil DPRINTF("kp.p_sigignore=" 8411.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8421.90Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 8431.90Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 8441.90Skamil 8451.90Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore))); 8461.90Skamil 8471.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 8481.88Skamil switch (sig) { 8491.88Skamil case SIGTRAP: 8501.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 8511.88Skamil break; 8521.88Skamil case SIGSEGV: 8531.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 8541.88Skamil break; 8551.88Skamil case SIGILL: 8561.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 8571.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 8581.88Skamil break; 8591.88Skamil case SIGFPE: 8601.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 8611.88Skamil break; 8621.88Skamil case SIGBUS: 8631.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 8641.88Skamil break; 8651.88Skamil } 8661.88Skamil 8671.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 8681.88Skamil 8691.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8701.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8711.88Skamil 8721.88Skamil validate_status_signaled(status, SIGKILL, 0); 8731.88Skamil 8741.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8751.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 8761.88Skamil} 8771.88Skamil 8781.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig) \ 8791.88SkamilATF_TC(test); \ 8801.88SkamilATF_TC_HEAD(test, tc) \ 8811.88Skamil{ \ 8821.88Skamil atf_tc_set_md_var(tc, "descr", \ 8831.88Skamil "Verify ignored crash signal " #sig " in a child after " \ 8841.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 8851.88Skamil} \ 8861.88Skamil \ 8871.88SkamilATF_TC_BODY(test, tc) \ 8881.88Skamil{ \ 8891.88Skamil \ 8901.88Skamil traceme_signalignored_crash(sig); \ 8911.88Skamil} 8921.88Skamil 8931.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP) 8941.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV) 8951.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL) 8961.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE) 8971.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS) 8981.88Skamil 8991.88Skamil/// ---------------------------------------------------------------------------- 9001.88Skamil 9011.88Skamilstatic void 9021.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught) 9031.1Skamil{ 9041.1Skamil const int exitval = 5; 9051.34Skamil const int sigval = SIGSTOP; 9061.1Skamil pid_t child, wpid; 9071.1Skamil struct sigaction sa; 9081.1Skamil#if defined(TWAIT_HAVE_STATUS) 9091.1Skamil int status; 9101.1Skamil#endif 9111.61Skre struct ptrace_siginfo info; 9121.1Skamil 9131.45Skamil memset(&info, 0, sizeof(info)); 9141.45Skamil 9151.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 9161.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 9171.1Skamil if (child == 0) { 9181.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 9191.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 9201.1Skamil 9211.34Skamil sa.sa_handler = sah; 9221.1Skamil sa.sa_flags = SA_SIGINFO; 9231.1Skamil sigemptyset(&sa.sa_mask); 9241.1Skamil 9251.1Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 9261.1Skamil 9271.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 9281.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 9291.1Skamil 9301.34Skamil FORKEE_ASSERT_EQ(*traceme_caught, 1); 9311.1Skamil 9321.13Schristos DPRINTF("Before exiting of the child process\n"); 9331.1Skamil _exit(exitval); 9341.1Skamil } 9351.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 9361.1Skamil 9371.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9381.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9391.1Skamil 9401.1Skamil validate_status_stopped(status, sigval); 9411.1Skamil 9421.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 9431.61Skre SYSCALL_REQUIRE( 9441.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 9451.45Skamil 9461.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 9471.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 9481.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 9491.45Skamil info.psi_siginfo.si_errno); 9501.45Skamil 9511.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 9521.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 9531.45Skamil 9541.13Schristos DPRINTF("Before resuming the child process where it left off and with " 9551.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 9561.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 9571.1Skamil 9581.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9591.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9601.1Skamil 9611.1Skamil validate_status_exited(status, exitval); 9621.1Skamil 9631.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 9641.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 9651.1Skamil} 9661.1Skamil 9671.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig) \ 9681.61SkreATF_TC(test); \ 9691.61SkreATF_TC_HEAD(test, tc) \ 9701.61Skre{ \ 9711.61Skre atf_tc_set_md_var(tc, "descr", \ 9721.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 9731.61Skre "handled correctly and caught by a signal handler"); \ 9741.61Skre} \ 9751.61Skre \ 9761.61Skrestatic int test##_caught = 0; \ 9771.61Skre \ 9781.61Skrestatic void \ 9791.61Skretest##_sighandler(int arg) \ 9801.61Skre{ \ 9811.61Skre FORKEE_ASSERT_EQ(arg, sig); \ 9821.61Skre \ 9831.61Skre ++ test##_caught; \ 9841.61Skre} \ 9851.61Skre \ 9861.61SkreATF_TC_BODY(test, tc) \ 9871.61Skre{ \ 9881.61Skre \ 9891.61Skre traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \ 9901.34Skamil} 9911.34Skamil 9921.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered. 9931.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */ 9941.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP) /* hangup */ 9951.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */ 9961.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */ 9971.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */ 9981.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */ 9991.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */ 10001.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */ 10011.34Skamil 10021.34Skamil/// ---------------------------------------------------------------------------- 10031.34Skamil 10041.35Skamilstatic void 10051.50Skamiltraceme_sendsignal_masked(int sigsent) 10061.50Skamil{ 10071.50Skamil const int exitval = 5; 10081.50Skamil const int sigval = SIGSTOP; 10091.50Skamil pid_t child, wpid; 10101.50Skamil sigset_t set; 10111.50Skamil#if defined(TWAIT_HAVE_STATUS) 10121.50Skamil int status; 10131.50Skamil#endif 10141.61Skre struct ptrace_siginfo info; 10151.50Skamil 10161.50Skamil memset(&info, 0, sizeof(info)); 10171.50Skamil 10181.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 10191.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 10201.50Skamil if (child == 0) { 10211.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 10221.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 10231.50Skamil 10241.50Skamil sigemptyset(&set); 10251.50Skamil sigaddset(&set, sigsent); 10261.50Skamil FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 10271.50Skamil 10281.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 10291.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 10301.50Skamil 10311.50Skamil _exit(exitval); 10321.50Skamil } 10331.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 10341.50Skamil 10351.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10361.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10371.50Skamil 10381.50Skamil validate_status_stopped(status, sigval); 10391.50Skamil 10401.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 10411.61Skre SYSCALL_REQUIRE( 10421.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 10431.50Skamil 10441.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 10451.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 10461.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 10471.50Skamil info.psi_siginfo.si_errno); 10481.50Skamil 10491.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 10501.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 10511.50Skamil 10521.50Skamil DPRINTF("Before resuming the child process where it left off and with " 10531.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 10541.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 10551.50Skamil 10561.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10571.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10581.50Skamil 10591.50Skamil validate_status_exited(status, exitval); 10601.50Skamil 10611.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 10621.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 10631.50Skamil} 10641.50Skamil 10651.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig) \ 10661.61SkreATF_TC(test); \ 10671.61SkreATF_TC_HEAD(test, tc) \ 10681.61Skre{ \ 10691.61Skre atf_tc_set_md_var(tc, "descr", \ 10701.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 10711.61Skre "handled correctly and the signal is masked by SIG_BLOCK"); \ 10721.61Skre} \ 10731.61Skre \ 10741.61SkreATF_TC_BODY(test, tc) \ 10751.61Skre{ \ 10761.61Skre \ 10771.61Skre traceme_sendsignal_masked(sig); \ 10781.50Skamil} 10791.50Skamil 10801.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 10811.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */ 10821.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP) /* hangup */ 10831.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */ 10841.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */ 10851.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */ 10861.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */ 10871.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */ 10881.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */ 10891.50Skamil 10901.50Skamil/// ---------------------------------------------------------------------------- 10911.50Skamil 10921.50Skamilstatic void 10931.50Skamiltraceme_sendsignal_ignored(int sigsent) 10941.50Skamil{ 10951.50Skamil const int exitval = 5; 10961.50Skamil const int sigval = SIGSTOP; 10971.50Skamil pid_t child, wpid; 10981.50Skamil struct sigaction sa; 10991.50Skamil#if defined(TWAIT_HAVE_STATUS) 11001.50Skamil int status; 11011.50Skamil#endif 11021.61Skre struct ptrace_siginfo info; 11031.50Skamil 11041.50Skamil memset(&info, 0, sizeof(info)); 11051.50Skamil 11061.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 11071.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 11081.50Skamil if (child == 0) { 11091.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 11101.61Skre 11111.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 11121.50Skamil 11131.50Skamil memset(&sa, 0, sizeof(sa)); 11141.50Skamil sa.sa_handler = SIG_IGN; 11151.50Skamil sigemptyset(&sa.sa_mask); 11161.50Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 11171.50Skamil 11181.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 11191.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 11201.50Skamil 11211.50Skamil _exit(exitval); 11221.50Skamil } 11231.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 11241.50Skamil 11251.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11261.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11271.50Skamil 11281.50Skamil validate_status_stopped(status, sigval); 11291.50Skamil 11301.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 11311.61Skre SYSCALL_REQUIRE( 11321.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 11331.50Skamil 11341.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 11351.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 11361.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 11371.50Skamil info.psi_siginfo.si_errno); 11381.50Skamil 11391.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 11401.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 11411.50Skamil 11421.50Skamil DPRINTF("Before resuming the child process where it left off and with " 11431.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 11441.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 11451.50Skamil 11461.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11471.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11481.50Skamil 11491.50Skamil validate_status_exited(status, exitval); 11501.50Skamil 11511.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 11521.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 11531.50Skamil} 11541.50Skamil 11551.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig) \ 11561.61SkreATF_TC(test); \ 11571.61SkreATF_TC_HEAD(test, tc) \ 11581.61Skre{ \ 11591.61Skre atf_tc_set_md_var(tc, "descr", \ 11601.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 11611.61Skre "handled correctly and the signal is masked by SIG_IGN"); \ 11621.61Skre} \ 11631.61Skre \ 11641.61SkreATF_TC_BODY(test, tc) \ 11651.61Skre{ \ 11661.61Skre \ 11671.61Skre traceme_sendsignal_ignored(sig); \ 11681.50Skamil} 11691.50Skamil 11701.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 11711.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */ 11721.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP) /* hangup */ 11731.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */ 11741.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */ 11751.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */ 11761.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */ 11771.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */ 11781.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */ 11791.50Skamil 11801.50Skamil/// ---------------------------------------------------------------------------- 11811.50Skamil 11821.50Skamilstatic void 11831.50Skamiltraceme_sendsignal_simple(int sigsent) 11841.1Skamil{ 11851.35Skamil const int sigval = SIGSTOP; 11861.35Skamil int exitval = 0; 11871.1Skamil pid_t child, wpid; 11881.1Skamil#if defined(TWAIT_HAVE_STATUS) 11891.1Skamil int status; 11901.85Skamil int expect_core; 11911.85Skamil 11921.85Skamil switch (sigsent) { 11931.85Skamil case SIGABRT: 11941.85Skamil case SIGTRAP: 11951.85Skamil case SIGBUS: 11961.85Skamil case SIGILL: 11971.85Skamil case SIGFPE: 11981.85Skamil case SIGSEGV: 11991.85Skamil expect_core = 1; 12001.85Skamil break; 12011.85Skamil default: 12021.85Skamil expect_core = 0; 12031.85Skamil break; 12041.85Skamil } 12051.1Skamil#endif 12061.61Skre struct ptrace_siginfo info; 12071.1Skamil 12081.45Skamil memset(&info, 0, sizeof(info)); 12091.45Skamil 12101.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 12111.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 12121.1Skamil if (child == 0) { 12131.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 12141.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 12151.1Skamil 12161.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 12171.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 12181.1Skamil 12191.35Skamil switch (sigsent) { 12201.35Skamil case SIGCONT: 12211.48Skamil case SIGSTOP: 12221.35Skamil _exit(exitval); 12231.35Skamil default: 12241.35Skamil /* NOTREACHED */ 12251.35Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 12261.35Skamil } 12271.1Skamil } 12281.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 12291.1Skamil 12301.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12311.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12321.1Skamil 12331.1Skamil validate_status_stopped(status, sigval); 12341.1Skamil 12351.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 12361.61Skre SYSCALL_REQUIRE( 12371.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 12381.45Skamil 12391.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12401.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 12411.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12421.45Skamil info.psi_siginfo.si_errno); 12431.45Skamil 12441.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12451.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12461.45Skamil 12471.13Schristos DPRINTF("Before resuming the child process where it left off and with " 12481.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 12491.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 12501.1Skamil 12511.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12521.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12531.1Skamil 12541.35Skamil switch (sigsent) { 12551.48Skamil case SIGSTOP: 12561.48Skamil validate_status_stopped(status, sigsent); 12571.48Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 12581.61Skre "child\n"); 12591.48Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 12601.61Skre sizeof(info)) != -1); 12611.48Skamil 12621.48Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12631.48Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 12641.61Skre "si_errno=%#x\n", 12651.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12661.61Skre info.psi_siginfo.si_errno); 12671.48Skamil 12681.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12691.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12701.48Skamil 12711.48Skamil DPRINTF("Before resuming the child process where it left off " 12721.61Skre "and with signal %s to be sent\n", strsignal(sigsent)); 12731.48Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 12741.48Skamil 12751.48Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12761.48Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 12771.61Skre child); 12781.48Skamil /* FALLTHROUGH */ 12791.35Skamil case SIGCONT: 12801.35Skamil validate_status_exited(status, exitval); 12811.35Skamil break; 12821.35Skamil default: 12831.35Skamil validate_status_signaled(status, sigsent, expect_core); 12841.35Skamil break; 12851.35Skamil } 12861.1Skamil 12871.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 12881.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 12891.1Skamil} 12901.1Skamil 12911.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig) \ 12921.61SkreATF_TC(test); \ 12931.61SkreATF_TC_HEAD(test, tc) \ 12941.61Skre{ \ 12951.61Skre atf_tc_set_md_var(tc, "descr", \ 12961.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 12971.61Skre "handled correctly in a child without a signal handler"); \ 12981.61Skre} \ 12991.61Skre \ 13001.61SkreATF_TC_BODY(test, tc) \ 13011.61Skre{ \ 13021.61Skre \ 13031.61Skre traceme_sendsignal_simple(sig); \ 13041.35Skamil} 13051.35Skamil 13061.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/ 13071.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/ 13081.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */ 13091.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP) /* hangup */ 13101.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */ 13111.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */ 13121.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */ 13131.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */ 13141.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */ 13151.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */ 13161.35Skamil 13171.35Skamil/// ---------------------------------------------------------------------------- 13181.35Skamil 13191.37SkamilATF_TC(traceme_pid1_parent); 13201.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc) 13211.37Skamil{ 13221.37Skamil atf_tc_set_md_var(tc, "descr", 13231.37Skamil "Verify that PT_TRACE_ME is not allowed when our parent is PID1"); 13241.37Skamil} 13251.37Skamil 13261.37SkamilATF_TC_BODY(traceme_pid1_parent, tc) 13271.37Skamil{ 13281.37Skamil struct msg_fds parent_child; 13291.37Skamil int exitval_child1 = 1, exitval_child2 = 2; 13301.37Skamil pid_t child1, child2, wpid; 13311.37Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 13321.37Skamil#if defined(TWAIT_HAVE_STATUS) 13331.37Skamil int status; 13341.37Skamil#endif 13351.37Skamil 13361.37Skamil SYSCALL_REQUIRE(msg_open(&parent_child) == 0); 13371.37Skamil 13381.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13391.37Skamil SYSCALL_REQUIRE((child1 = fork()) != -1); 13401.37Skamil if (child1 == 0) { 13411.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13421.37Skamil SYSCALL_REQUIRE((child2 = fork()) != -1); 13431.37Skamil if (child2 != 0) { 13441.37Skamil DPRINTF("Parent process PID=%d, child2's PID=%d\n", 13451.61Skre getpid(), child2); 13461.37Skamil _exit(exitval_child1); 13471.37Skamil } 13481.37Skamil CHILD_FROM_PARENT("exit child1", parent_child, msg); 13491.37Skamil 13501.37Skamil DPRINTF("Assert that our parent is PID1 (initproc)\n"); 13511.37Skamil FORKEE_ASSERT_EQ(getppid(), 1); 13521.37Skamil 13531.37Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 13541.37Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1); 13551.37Skamil SYSCALL_REQUIRE_ERRNO(errno, EPERM); 13561.37Skamil 13571.37Skamil CHILD_TO_PARENT("child2 exiting", parent_child, msg); 13581.37Skamil 13591.37Skamil _exit(exitval_child2); 13601.37Skamil } 13611.37Skamil DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1); 13621.37Skamil 13631.37Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 13641.61Skre TWAIT_REQUIRE_SUCCESS( 13651.61Skre wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1); 13661.37Skamil 13671.37Skamil validate_status_exited(status, exitval_child1); 13681.37Skamil 13691.37Skamil DPRINTF("Notify that child1 is dead\n"); 13701.37Skamil PARENT_TO_CHILD("exit child1", parent_child, msg); 13711.37Skamil 13721.37Skamil DPRINTF("Wait for exiting of child2\n"); 13731.37Skamil PARENT_FROM_CHILD("child2 exiting", parent_child, msg); 13741.37Skamil} 13751.37Skamil 13761.37Skamil/// ---------------------------------------------------------------------------- 13771.37Skamil 13781.40Skamilstatic void 13791.40Skamiltraceme_vfork_raise(int sigval) 13801.40Skamil{ 13811.46Skamil const int exitval = 5, exitval_watcher = 10; 13821.46Skamil pid_t child, parent, watcher, wpid; 13831.46Skamil int rv; 13841.40Skamil#if defined(TWAIT_HAVE_STATUS) 13851.40Skamil int status; 13861.85Skamil 13871.85Skamil /* volatile workarounds GCC -Werror=clobbered */ 13881.85Skamil volatile int expect_core; 13891.85Skamil 13901.85Skamil switch (sigval) { 13911.85Skamil case SIGABRT: 13921.85Skamil case SIGTRAP: 13931.85Skamil case SIGBUS: 13941.85Skamil case SIGILL: 13951.85Skamil case SIGFPE: 13961.85Skamil case SIGSEGV: 13971.85Skamil expect_core = 1; 13981.85Skamil break; 13991.85Skamil default: 14001.85Skamil expect_core = 0; 14011.85Skamil break; 14021.85Skamil } 14031.40Skamil#endif 14041.40Skamil 14051.46Skamil /* 14061.46Skamil * Spawn a dedicated thread to watch for a stopped child and emit 14071.46Skamil * the SIGKILL signal to it. 14081.46Skamil * 14091.46Skamil * vfork(2) might clobber watcher, this means that it's safer and 14101.46Skamil * simpler to reparent this process to initproc and forget about it. 14111.46Skamil */ 14121.46Skamil if (sigval == SIGSTOP) { 14131.46Skamil parent = getpid(); 14141.46Skamil 14151.46Skamil watcher = fork(); 14161.46Skamil ATF_REQUIRE(watcher != 1); 14171.46Skamil if (watcher == 0) { 14181.46Skamil /* Double fork(2) trick to reparent to initproc */ 14191.46Skamil watcher = fork(); 14201.46Skamil FORKEE_ASSERT_NEQ(watcher, -1); 14211.46Skamil if (watcher != 0) 14221.46Skamil _exit(exitval_watcher); 14231.46Skamil 14241.46Skamil child = await_stopped_child(parent); 14251.46Skamil 14261.46Skamil errno = 0; 14271.46Skamil rv = kill(child, SIGKILL); 14281.46Skamil FORKEE_ASSERT_EQ(rv, 0); 14291.46Skamil FORKEE_ASSERT_EQ(errno, 0); 14301.46Skamil 14311.46Skamil /* This exit value will be collected by initproc */ 14321.46Skamil _exit(0); 14331.46Skamil } 14341.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14351.46Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0), 14361.61Skre watcher); 14371.46Skamil 14381.46Skamil validate_status_exited(status, exitval_watcher); 14391.46Skamil 14401.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14411.61Skre TWAIT_REQUIRE_FAILURE(ECHILD, 14421.61Skre wpid = TWAIT_GENERIC(watcher, &status, 0)); 14431.46Skamil } 14441.46Skamil 14451.40Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 14461.40Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 14471.40Skamil if (child == 0) { 14481.40Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 14491.40Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 14501.40Skamil 14511.40Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 14521.40Skamil FORKEE_ASSERT(raise(sigval) == 0); 14531.40Skamil 14541.40Skamil switch (sigval) { 14551.46Skamil case SIGSTOP: 14561.40Skamil case SIGKILL: 14571.40Skamil case SIGABRT: 14581.40Skamil case SIGHUP: 14591.85Skamil case SIGTRAP: 14601.85Skamil case SIGBUS: 14611.85Skamil case SIGILL: 14621.85Skamil case SIGFPE: 14631.85Skamil case SIGSEGV: 14641.40Skamil /* NOTREACHED */ 14651.40Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 14661.70Smrg __unreachable(); 14671.40Skamil default: 14681.40Skamil DPRINTF("Before exiting of the child process\n"); 14691.40Skamil _exit(exitval); 14701.40Skamil } 14711.40Skamil } 14721.40Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 14731.40Skamil 14741.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14751.40Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 14761.40Skamil 14771.40Skamil switch (sigval) { 14781.40Skamil case SIGKILL: 14791.40Skamil case SIGABRT: 14801.40Skamil case SIGHUP: 14811.85Skamil case SIGTRAP: 14821.85Skamil case SIGBUS: 14831.85Skamil case SIGILL: 14841.85Skamil case SIGFPE: 14851.85Skamil case SIGSEGV: 14861.40Skamil validate_status_signaled(status, sigval, expect_core); 14871.40Skamil break; 14881.40Skamil case SIGSTOP: 14891.46Skamil validate_status_signaled(status, SIGKILL, 0); 14901.46Skamil break; 14911.40Skamil case SIGCONT: 14921.47Skamil case SIGTSTP: 14931.47Skamil case SIGTTIN: 14941.47Skamil case SIGTTOU: 14951.40Skamil validate_status_exited(status, exitval); 14961.40Skamil break; 14971.40Skamil default: 14981.40Skamil /* NOTREACHED */ 14991.40Skamil ATF_REQUIRE(0 && "NOT IMPLEMENTED"); 15001.40Skamil break; 15011.40Skamil } 15021.40Skamil 15031.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15041.40Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15051.40Skamil} 15061.40Skamil 15071.61Skre#define TRACEME_VFORK_RAISE(test, sig) \ 15081.61SkreATF_TC(test); \ 15091.61SkreATF_TC_HEAD(test, tc) \ 15101.61Skre{ \ 15111.61Skre atf_tc_set_md_var(tc, "descr", \ 15121.61Skre "Verify PT_TRACE_ME followed by raise of " #sig " in a " \ 15131.61Skre "vfork(2)ed child"); \ 15141.61Skre} \ 15151.61Skre \ 15161.61SkreATF_TC_BODY(test, tc) \ 15171.61Skre{ \ 15181.61Skre \ 15191.61Skre traceme_vfork_raise(sig); \ 15201.40Skamil} 15211.40Skamil 15221.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */ 15231.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */ 15241.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */ 15251.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */ 15261.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */ 15271.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */ 15281.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP) /* hangup */ 15291.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */ 15301.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */ 15311.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */ 15321.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */ 15331.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */ 15341.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */ 15351.40Skamil 15361.40Skamil/// ---------------------------------------------------------------------------- 15371.40Skamil 15381.52Skamilstatic void 15391.52Skamiltraceme_vfork_crash(int sig) 15401.41Skamil{ 15411.41Skamil pid_t child, wpid; 15421.41Skamil#if defined(TWAIT_HAVE_STATUS) 15431.41Skamil int status; 15441.41Skamil#endif 15451.41Skamil 15461.71Skamil#ifndef PTRACE_ILLEGAL_ASM 15471.71Skamil if (sig == SIGILL) 15481.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 15491.71Skamil#endif 15501.71Skamil 15511.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 15521.114Skamil atf_tc_skip("FP exceptions are not supported"); 15531.114Skamil 15541.41Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 15551.41Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 15561.41Skamil if (child == 0) { 15571.41Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 15581.41Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 15591.41Skamil 15601.52Skamil DPRINTF("Before executing a trap\n"); 15611.52Skamil switch (sig) { 15621.52Skamil case SIGTRAP: 15631.52Skamil trigger_trap(); 15641.52Skamil break; 15651.52Skamil case SIGSEGV: 15661.52Skamil trigger_segv(); 15671.52Skamil break; 15681.52Skamil case SIGILL: 15691.52Skamil trigger_ill(); 15701.52Skamil break; 15711.52Skamil case SIGFPE: 15721.52Skamil trigger_fpe(); 15731.52Skamil break; 15741.52Skamil case SIGBUS: 15751.52Skamil trigger_bus(); 15761.52Skamil break; 15771.52Skamil default: 15781.52Skamil /* NOTREACHED */ 15791.52Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15801.52Skamil } 15811.41Skamil 15821.41Skamil /* NOTREACHED */ 15831.41Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15841.41Skamil } 15851.41Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 15861.41Skamil 15871.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15881.41Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 15891.41Skamil 15901.52Skamil validate_status_signaled(status, sig, 1); 15911.41Skamil 15921.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15931.41Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15941.41Skamil} 15951.41Skamil 15961.61Skre#define TRACEME_VFORK_CRASH(test, sig) \ 15971.61SkreATF_TC(test); \ 15981.61SkreATF_TC_HEAD(test, tc) \ 15991.61Skre{ \ 16001.61Skre atf_tc_set_md_var(tc, "descr", \ 16011.61Skre "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16021.61Skre "vfork(2)ed child"); \ 16031.61Skre} \ 16041.61Skre \ 16051.61SkreATF_TC_BODY(test, tc) \ 16061.61Skre{ \ 16071.61Skre \ 16081.61Skre traceme_vfork_crash(sig); \ 16091.52Skamil} 16101.52Skamil 16111.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP) 16121.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV) 16131.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL) 16141.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE) 16151.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS) 16161.52Skamil 16171.41Skamil/// ---------------------------------------------------------------------------- 16181.41Skamil 16191.92Skamilstatic void 16201.92Skamiltraceme_vfork_signalmasked_crash(int sig) 16211.92Skamil{ 16221.92Skamil pid_t child, wpid; 16231.92Skamil#if defined(TWAIT_HAVE_STATUS) 16241.92Skamil int status; 16251.92Skamil#endif 16261.92Skamil sigset_t intmask; 16271.92Skamil 16281.92Skamil#ifndef PTRACE_ILLEGAL_ASM 16291.92Skamil if (sig == SIGILL) 16301.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 16311.92Skamil#endif 16321.92Skamil 16331.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 16341.114Skamil atf_tc_skip("FP exceptions are not supported"); 16351.114Skamil 16361.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 16371.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 16381.92Skamil if (child == 0) { 16391.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 16401.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 16411.92Skamil 16421.92Skamil sigemptyset(&intmask); 16431.92Skamil sigaddset(&intmask, sig); 16441.92Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 16451.92Skamil 16461.92Skamil DPRINTF("Before executing a trap\n"); 16471.92Skamil switch (sig) { 16481.92Skamil case SIGTRAP: 16491.92Skamil trigger_trap(); 16501.92Skamil break; 16511.92Skamil case SIGSEGV: 16521.92Skamil trigger_segv(); 16531.92Skamil break; 16541.92Skamil case SIGILL: 16551.92Skamil trigger_ill(); 16561.92Skamil break; 16571.92Skamil case SIGFPE: 16581.92Skamil trigger_fpe(); 16591.92Skamil break; 16601.92Skamil case SIGBUS: 16611.92Skamil trigger_bus(); 16621.92Skamil break; 16631.92Skamil default: 16641.92Skamil /* NOTREACHED */ 16651.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16661.92Skamil } 16671.92Skamil 16681.92Skamil /* NOTREACHED */ 16691.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16701.92Skamil } 16711.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 16721.92Skamil 16731.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16741.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 16751.92Skamil 16761.92Skamil validate_status_signaled(status, sig, 1); 16771.92Skamil 16781.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16791.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 16801.92Skamil} 16811.92Skamil 16821.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig) \ 16831.92SkamilATF_TC(test); \ 16841.92SkamilATF_TC_HEAD(test, tc) \ 16851.92Skamil{ \ 16861.92Skamil atf_tc_set_md_var(tc, "descr", \ 16871.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16881.92Skamil "vfork(2)ed child with a masked signal"); \ 16891.92Skamil} \ 16901.92Skamil \ 16911.92SkamilATF_TC_BODY(test, tc) \ 16921.92Skamil{ \ 16931.92Skamil \ 16941.92Skamil traceme_vfork_signalmasked_crash(sig); \ 16951.92Skamil} 16961.92Skamil 16971.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP) 16981.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV) 16991.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL) 17001.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE) 17011.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS) 17021.92Skamil 17031.92Skamil/// ---------------------------------------------------------------------------- 17041.92Skamil 17051.92Skamilstatic void 17061.92Skamiltraceme_vfork_signalignored_crash(int sig) 17071.92Skamil{ 17081.92Skamil pid_t child, wpid; 17091.92Skamil#if defined(TWAIT_HAVE_STATUS) 17101.92Skamil int status; 17111.92Skamil#endif 17121.92Skamil struct sigaction sa; 17131.92Skamil 17141.92Skamil#ifndef PTRACE_ILLEGAL_ASM 17151.92Skamil if (sig == SIGILL) 17161.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 17171.92Skamil#endif 17181.92Skamil 17191.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 17201.114Skamil atf_tc_skip("FP exceptions are not supported"); 17211.114Skamil 17221.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 17231.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 17241.92Skamil if (child == 0) { 17251.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 17261.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 17271.92Skamil 17281.92Skamil memset(&sa, 0, sizeof(sa)); 17291.92Skamil sa.sa_handler = SIG_IGN; 17301.92Skamil sigemptyset(&sa.sa_mask); 17311.92Skamil 17321.92Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 17331.92Skamil 17341.92Skamil DPRINTF("Before executing a trap\n"); 17351.92Skamil switch (sig) { 17361.92Skamil case SIGTRAP: 17371.92Skamil trigger_trap(); 17381.92Skamil break; 17391.92Skamil case SIGSEGV: 17401.92Skamil trigger_segv(); 17411.92Skamil break; 17421.92Skamil case SIGILL: 17431.92Skamil trigger_ill(); 17441.92Skamil break; 17451.92Skamil case SIGFPE: 17461.92Skamil trigger_fpe(); 17471.92Skamil break; 17481.92Skamil case SIGBUS: 17491.92Skamil trigger_bus(); 17501.92Skamil break; 17511.92Skamil default: 17521.92Skamil /* NOTREACHED */ 17531.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17541.92Skamil } 17551.92Skamil 17561.92Skamil /* NOTREACHED */ 17571.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17581.92Skamil } 17591.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 17601.92Skamil 17611.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17621.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17631.92Skamil 17641.92Skamil validate_status_signaled(status, sig, 1); 17651.92Skamil 17661.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17671.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 17681.92Skamil} 17691.92Skamil 17701.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig) \ 17711.92SkamilATF_TC(test); \ 17721.92SkamilATF_TC_HEAD(test, tc) \ 17731.92Skamil{ \ 17741.92Skamil atf_tc_set_md_var(tc, "descr", \ 17751.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 17761.92Skamil "vfork(2)ed child with ignored signal"); \ 17771.92Skamil} \ 17781.92Skamil \ 17791.92SkamilATF_TC_BODY(test, tc) \ 17801.92Skamil{ \ 17811.92Skamil \ 17821.92Skamil traceme_vfork_signalignored_crash(sig); \ 17831.92Skamil} 17841.92Skamil 17851.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap, 17861.92Skamil SIGTRAP) 17871.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv, 17881.92Skamil SIGSEGV) 17891.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill, 17901.92Skamil SIGILL) 17911.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe, 17921.92Skamil SIGFPE) 17931.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus, 17941.92Skamil SIGBUS) 17951.92Skamil 17961.92Skamil/// ---------------------------------------------------------------------------- 17971.92Skamil 17981.96Skamilstatic void 17991.96Skamiltraceme_vfork_exec(bool masked, bool ignored) 18001.43Skamil{ 18011.43Skamil const int sigval = SIGTRAP; 18021.43Skamil pid_t child, wpid; 18031.43Skamil#if defined(TWAIT_HAVE_STATUS) 18041.43Skamil int status; 18051.43Skamil#endif 18061.96Skamil struct sigaction sa; 18071.61Skre struct ptrace_siginfo info; 18081.96Skamil sigset_t intmask; 18091.96Skamil struct kinfo_proc2 kp; 18101.96Skamil size_t len = sizeof(kp); 18111.96Skamil 18121.96Skamil int name[6]; 18131.96Skamil const size_t namelen = __arraycount(name); 18141.96Skamil ki_sigset_t kp_sigmask; 18151.96Skamil ki_sigset_t kp_sigignore; 18161.43Skamil 18171.43Skamil memset(&info, 0, sizeof(info)); 18181.43Skamil 18191.43Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 18201.43Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 18211.43Skamil if (child == 0) { 18221.43Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 18231.43Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 18241.43Skamil 18251.96Skamil if (masked) { 18261.96Skamil sigemptyset(&intmask); 18271.96Skamil sigaddset(&intmask, sigval); 18281.96Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 18291.96Skamil } 18301.96Skamil 18311.96Skamil if (ignored) { 18321.96Skamil memset(&sa, 0, sizeof(sa)); 18331.96Skamil sa.sa_handler = SIG_IGN; 18341.96Skamil sigemptyset(&sa.sa_mask); 18351.96Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 18361.96Skamil } 18371.96Skamil 18381.43Skamil DPRINTF("Before calling execve(2) from child\n"); 18391.43Skamil execlp("/bin/echo", "/bin/echo", NULL); 18401.43Skamil 18411.43Skamil /* NOTREACHED */ 18421.43Skamil FORKEE_ASSERTX(0 && "Not reached"); 18431.43Skamil } 18441.43Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 18451.43Skamil 18461.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 18471.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 18481.43Skamil 18491.43Skamil validate_status_stopped(status, sigval); 18501.43Skamil 18511.96Skamil name[0] = CTL_KERN, 18521.96Skamil name[1] = KERN_PROC2, 18531.96Skamil name[2] = KERN_PROC_PID; 18541.96Skamil name[3] = getpid(); 18551.96Skamil name[4] = sizeof(kp); 18561.96Skamil name[5] = 1; 18571.96Skamil 18581.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18591.96Skamil 18601.96Skamil if (masked) 18611.96Skamil kp_sigmask = kp.p_sigmask; 18621.96Skamil 18631.96Skamil if (ignored) 18641.96Skamil kp_sigignore = kp.p_sigignore; 18651.96Skamil 18661.96Skamil name[3] = getpid(); 18671.96Skamil 18681.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18691.96Skamil 18701.96Skamil if (masked) { 18711.96Skamil DPRINTF("kp_sigmask=" 18721.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18731.96Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 18741.96Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 18751.96Skamil 18761.96Skamil DPRINTF("kp.p_sigmask=" 18771.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18781.96Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 18791.96Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 18801.96Skamil 18811.96Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 18821.96Skamil sizeof(kp_sigmask))); 18831.96Skamil } 18841.96Skamil 18851.96Skamil if (ignored) { 18861.96Skamil DPRINTF("kp_sigignore=" 18871.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18881.96Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 18891.96Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 18901.96Skamil 18911.96Skamil DPRINTF("kp.p_sigignore=" 18921.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18931.96Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 18941.96Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 18951.96Skamil 18961.96Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 18971.96Skamil sizeof(kp_sigignore))); 18981.96Skamil } 18991.96Skamil 19001.43Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 19011.61Skre SYSCALL_REQUIRE( 19021.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 19031.43Skamil 19041.43Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 19051.43Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 19061.43Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 19071.43Skamil info.psi_siginfo.si_errno); 19081.43Skamil 19091.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 19101.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 19111.43Skamil 19121.43Skamil DPRINTF("Before resuming the child process where it left off and " 19131.43Skamil "without signal to be sent\n"); 19141.43Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 19151.43Skamil 19161.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19171.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 19181.43Skamil 19191.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19201.43Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 19211.43Skamil} 19221.43Skamil 19231.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored) \ 19241.96SkamilATF_TC(test); \ 19251.96SkamilATF_TC_HEAD(test, tc) \ 19261.96Skamil{ \ 19271.96Skamil atf_tc_set_md_var(tc, "descr", \ 19281.96Skamil "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed " \ 19291.96Skamil "child%s%s", masked ? " with masked signal" : "", \ 19301.96Skamil masked ? " with ignored signal" : ""); \ 19311.96Skamil} \ 19321.96Skamil \ 19331.96SkamilATF_TC_BODY(test, tc) \ 19341.96Skamil{ \ 19351.96Skamil \ 19361.96Skamil traceme_vfork_exec(masked, ignored); \ 19371.96Skamil} 19381.96Skamil 19391.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false) 19401.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false) 19411.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true) 19421.96Skamil 19431.43Skamil/// ---------------------------------------------------------------------------- 19441.43Skamil 19451.1Skamil#if defined(TWAIT_HAVE_PID) 19461.51Skamilstatic void 19471.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored) 19481.59Skamil{ 19491.94Skamil const int sigval = SIGSTOP; 19501.59Skamil struct msg_fds parent_tracee, parent_tracer; 19511.59Skamil const int exitval = 10; 19521.59Skamil pid_t tracee, tracer, wpid; 19531.59Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 19541.59Skamil#if defined(TWAIT_HAVE_STATUS) 19551.59Skamil int status; 19561.59Skamil#endif 19571.94Skamil struct sigaction sa; 19581.59Skamil struct ptrace_siginfo info; 19591.94Skamil sigset_t intmask; 19601.94Skamil struct kinfo_proc2 kp; 19611.94Skamil size_t len = sizeof(kp); 19621.94Skamil 19631.94Skamil int name[6]; 19641.94Skamil const size_t namelen = __arraycount(name); 19651.94Skamil ki_sigset_t kp_sigmask; 19661.94Skamil ki_sigset_t kp_sigignore; 19671.61Skre 19681.71Skamil#ifndef PTRACE_ILLEGAL_ASM 19691.71Skamil if (sig == SIGILL) 19701.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 19711.71Skamil#endif 19721.71Skamil 19731.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 19741.114Skamil atf_tc_skip("FP exceptions are not supported"); 19751.114Skamil 19761.59Skamil memset(&info, 0, sizeof(info)); 19771.59Skamil 19781.59Skamil DPRINTF("Spawn tracee\n"); 19791.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 19801.59Skamil tracee = atf_utils_fork(); 19811.59Skamil if (tracee == 0) { 19821.59Skamil // Wait for parent to let us crash 19831.59Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 19841.61Skre 19851.94Skamil if (masked) { 19861.94Skamil sigemptyset(&intmask); 19871.94Skamil sigaddset(&intmask, sig); 19881.94Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 19891.94Skamil } 19901.94Skamil 19911.94Skamil if (ignored) { 19921.94Skamil memset(&sa, 0, sizeof(sa)); 19931.94Skamil sa.sa_handler = SIG_IGN; 19941.94Skamil sigemptyset(&sa.sa_mask); 19951.94Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 19961.94Skamil } 19971.94Skamil 19981.94Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 19991.94Skamil FORKEE_ASSERT(raise(sigval) == 0); 20001.94Skamil 20011.59Skamil DPRINTF("Before executing a trap\n"); 20021.59Skamil switch (sig) { 20031.59Skamil case SIGTRAP: 20041.59Skamil trigger_trap(); 20051.59Skamil break; 20061.59Skamil case SIGSEGV: 20071.59Skamil trigger_segv(); 20081.59Skamil break; 20091.59Skamil case SIGILL: 20101.59Skamil trigger_ill(); 20111.59Skamil break; 20121.59Skamil case SIGFPE: 20131.59Skamil trigger_fpe(); 20141.59Skamil break; 20151.59Skamil case SIGBUS: 20161.59Skamil trigger_bus(); 20171.59Skamil break; 20181.59Skamil default: 20191.59Skamil /* NOTREACHED */ 20201.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20211.59Skamil } 20221.59Skamil 20231.59Skamil /* NOTREACHED */ 20241.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20251.59Skamil } 20261.59Skamil 20271.59Skamil DPRINTF("Spawn debugger\n"); 20281.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 20291.59Skamil tracer = atf_utils_fork(); 20301.59Skamil if (tracer == 0) { 20311.59Skamil /* Fork again and drop parent to reattach to PID 1 */ 20321.59Skamil tracer = atf_utils_fork(); 20331.59Skamil if (tracer != 0) 20341.61Skre _exit(exitval); 20351.59Skamil 20361.59Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 20371.59Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 20381.59Skamil 20391.59Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 20401.59Skamil FORKEE_REQUIRE_SUCCESS( 20411.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20421.59Skamil 20431.59Skamil forkee_status_stopped(status, SIGSTOP); 20441.59Skamil 20451.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20461.94Skamil "traced process\n"); 20471.94Skamil SYSCALL_REQUIRE( 20481.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20491.94Skamil 20501.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20511.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20521.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20531.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20541.94Skamil 20551.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 20561.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 20571.94Skamil 20581.59Skamil /* Resume tracee with PT_CONTINUE */ 20591.59Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 20601.59Skamil 20611.59Skamil /* Inform parent that tracer has attached to tracee */ 20621.59Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 20631.59Skamil 20641.59Skamil /* Wait for parent to tell use that tracee should have exited */ 20651.59Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 20661.59Skamil 20671.59Skamil /* Wait for tracee and assert that it exited */ 20681.59Skamil FORKEE_REQUIRE_SUCCESS( 20691.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20701.59Skamil 20711.94Skamil forkee_status_stopped(status, sigval); 20721.94Skamil 20731.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20741.94Skamil "traced process\n"); 20751.94Skamil SYSCALL_REQUIRE( 20761.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20771.94Skamil 20781.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20791.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20801.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20811.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20821.94Skamil 20831.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 20841.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 20851.94Skamil 20861.94Skamil name[0] = CTL_KERN, 20871.94Skamil name[1] = KERN_PROC2, 20881.94Skamil name[2] = KERN_PROC_PID; 20891.94Skamil name[3] = tracee; 20901.94Skamil name[4] = sizeof(kp); 20911.94Skamil name[5] = 1; 20921.94Skamil 20931.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 20941.94Skamil 20951.94Skamil if (masked) 20961.94Skamil kp_sigmask = kp.p_sigmask; 20971.94Skamil 20981.94Skamil if (ignored) 20991.94Skamil kp_sigignore = kp.p_sigignore; 21001.94Skamil 21011.94Skamil /* Resume tracee with PT_CONTINUE */ 21021.94Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 21031.94Skamil 21041.94Skamil /* Wait for tracee and assert that it exited */ 21051.94Skamil FORKEE_REQUIRE_SUCCESS( 21061.94Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21071.94Skamil 21081.93Skamil forkee_status_stopped(status, sig); 21091.59Skamil 21101.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 21111.61Skre "traced process\n"); 21121.61Skre SYSCALL_REQUIRE( 21131.61Skre ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 21141.59Skamil 21151.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21161.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21171.61Skre "si_errno=%#x\n", info.psi_siginfo.si_signo, 21181.61Skre info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 21191.59Skamil 21201.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig); 21211.94Skamil 21221.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21231.94Skamil 21241.94Skamil if (masked) { 21251.94Skamil DPRINTF("kp_sigmask=" 21261.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21271.94Skamil PRIx32 "\n", 21281.94Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 21291.94Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 21301.94Skamil 21311.94Skamil DPRINTF("kp.p_sigmask=" 21321.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21331.94Skamil PRIx32 "\n", 21341.94Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 21351.94Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 21361.94Skamil 21371.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask, 21381.94Skamil sizeof(kp_sigmask))); 21391.94Skamil } 21401.94Skamil 21411.94Skamil if (ignored) { 21421.94Skamil DPRINTF("kp_sigignore=" 21431.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21441.94Skamil PRIx32 "\n", 21451.94Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 21461.94Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 21471.94Skamil 21481.94Skamil DPRINTF("kp.p_sigignore=" 21491.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21501.94Skamil PRIx32 "\n", 21511.94Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 21521.94Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 21531.94Skamil 21541.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore, 21551.94Skamil sizeof(kp_sigignore))); 21561.94Skamil } 21571.94Skamil 21581.59Skamil switch (sig) { 21591.59Skamil case SIGTRAP: 21601.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 21611.59Skamil break; 21621.59Skamil case SIGSEGV: 21631.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 21641.59Skamil break; 21651.71Skamil case SIGILL: 21661.113Skamil FORKEE_ASSERT(info.psi_siginfo.si_code >= ILL_ILLOPC && 21671.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 21681.71Skamil break; 21691.59Skamil case SIGFPE: 21701.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 21711.59Skamil break; 21721.59Skamil case SIGBUS: 21731.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 21741.59Skamil break; 21751.59Skamil } 21761.59Skamil 21771.59Skamil FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1); 21781.59Skamil DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME); 21791.93Skamil FORKEE_REQUIRE_SUCCESS( 21801.61Skre wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21811.59Skamil 21821.93Skamil forkee_status_signaled(status, SIGKILL, 0); 21831.59Skamil 21841.71Skamil /* Inform parent that tracer is exiting normally */ 21851.71Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 21861.71Skamil 21871.59Skamil DPRINTF("Before exiting of the tracer process\n"); 21881.59Skamil _exit(0 /* collect by initproc */); 21891.59Skamil } 21901.59Skamil 21911.59Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 21921.59Skamil "calling %s()\n", TWAIT_FNAME); 21931.59Skamil TWAIT_REQUIRE_SUCCESS( 21941.59Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 21951.59Skamil 21961.59Skamil validate_status_exited(status, exitval); 21971.59Skamil 21981.59Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 21991.59Skamil TWAIT_FNAME); 22001.59Skamil TWAIT_REQUIRE_SUCCESS( 22011.59Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 22021.59Skamil 22031.59Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 22041.59Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 22051.59Skamil 22061.59Skamil DPRINTF("Resume the tracee and let it crash\n"); 22071.59Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 22081.59Skamil 22091.59Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 22101.59Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 22111.59Skamil 22121.59Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 22131.59Skamil TWAIT_FNAME); 22141.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22151.59Skamil 22161.59Skamil validate_status_signaled(status, SIGKILL, 0); 22171.59Skamil 22181.71Skamil DPRINTF("Await normal exit of tracer\n"); 22191.71Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 22201.71Skamil 22211.59Skamil msg_close(&parent_tracer); 22221.59Skamil msg_close(&parent_tracee); 22231.59Skamil} 22241.59Skamil 22251.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig) \ 22261.61SkreATF_TC(test); \ 22271.61SkreATF_TC_HEAD(test, tc) \ 22281.61Skre{ \ 22291.61Skre atf_tc_set_md_var(tc, "descr", \ 22301.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22311.94Skamil "the debuggee"); \ 22321.61Skre} \ 22331.61Skre \ 22341.61SkreATF_TC_BODY(test, tc) \ 22351.61Skre{ \ 22361.61Skre \ 22371.94Skamil unrelated_tracer_sees_crash(sig, false, false); \ 22381.59Skamil} 22391.59Skamil 22401.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP) 22411.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV) 22421.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL) 22431.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE) 22441.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS) 22451.94Skamil 22461.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig) \ 22471.94SkamilATF_TC(test); \ 22481.94SkamilATF_TC_HEAD(test, tc) \ 22491.94Skamil{ \ 22501.94Skamil atf_tc_set_md_var(tc, "descr", \ 22511.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22521.94Skamil "the debuggee with masked signal"); \ 22531.94Skamil} \ 22541.94Skamil \ 22551.94SkamilATF_TC_BODY(test, tc) \ 22561.94Skamil{ \ 22571.94Skamil \ 22581.94Skamil unrelated_tracer_sees_crash(sig, true, false); \ 22591.94Skamil} 22601.94Skamil 22611.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22621.94Skamil unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP) 22631.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22641.94Skamil unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV) 22651.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22661.94Skamil unrelated_tracer_sees_signalmasked_crash_ill, SIGILL) 22671.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22681.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE) 22691.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22701.94Skamil unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS) 22711.94Skamil 22721.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig) \ 22731.94SkamilATF_TC(test); \ 22741.94SkamilATF_TC_HEAD(test, tc) \ 22751.94Skamil{ \ 22761.94Skamil atf_tc_set_md_var(tc, "descr", \ 22771.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22781.94Skamil "the debuggee with signal ignored"); \ 22791.94Skamil} \ 22801.94Skamil \ 22811.94SkamilATF_TC_BODY(test, tc) \ 22821.94Skamil{ \ 22831.94Skamil \ 22841.94Skamil unrelated_tracer_sees_crash(sig, false, true); \ 22851.94Skamil} 22861.94Skamil 22871.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22881.94Skamil unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP) 22891.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22901.94Skamil unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV) 22911.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22921.94Skamil unrelated_tracer_sees_signalignored_crash_ill, SIGILL) 22931.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22941.94Skamil unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE) 22951.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22961.94Skamil unrelated_tracer_sees_signalignored_crash_bus, SIGBUS) 22971.59Skamil#endif 22981.59Skamil 22991.59Skamil/// ---------------------------------------------------------------------------- 23001.59Skamil 23011.59Skamil#if defined(TWAIT_HAVE_PID) 23021.59Skamilstatic void 23031.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated, 23041.67Skamil bool stopped) 23051.1Skamil{ 23061.51Skamil /* 23071.51Skamil * notimeout - disable timeout in await zombie function 23081.51Skamil * unrelated - attach from unrelated tracer reparented to initproc 23091.67Skamil * stopped - attach to a stopped process 23101.51Skamil */ 23111.1Skamil 23121.1Skamil struct msg_fds parent_tracee, parent_tracer; 23131.1Skamil const int exitval_tracee = 5; 23141.1Skamil const int exitval_tracer = 10; 23151.1Skamil pid_t tracee, tracer, wpid; 23161.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 23171.1Skamil#if defined(TWAIT_HAVE_STATUS) 23181.1Skamil int status; 23191.1Skamil#endif 23201.1Skamil 23211.67Skamil /* 23221.67Skamil * Only a subset of options are supported. 23231.67Skamil */ 23241.67Skamil ATF_REQUIRE((!notimeout && !unrelated && !stopped) || 23251.67Skamil (!notimeout && unrelated && !stopped) || 23261.67Skamil (notimeout && !unrelated && !stopped) || 23271.67Skamil (!notimeout && unrelated && stopped)); 23281.67Skamil 23291.13Schristos DPRINTF("Spawn tracee\n"); 23301.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 23311.1Skamil tracee = atf_utils_fork(); 23321.1Skamil if (tracee == 0) { 23331.67Skamil if (stopped) { 23341.67Skamil DPRINTF("Stop self PID %d\n", getpid()); 23351.67Skamil raise(SIGSTOP); 23361.67Skamil } 23371.67Skamil 23381.1Skamil // Wait for parent to let us exit 23391.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 23401.1Skamil _exit(exitval_tracee); 23411.1Skamil } 23421.1Skamil 23431.13Schristos DPRINTF("Spawn debugger\n"); 23441.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 23451.1Skamil tracer = atf_utils_fork(); 23461.1Skamil if (tracer == 0) { 23471.51Skamil if(unrelated) { 23481.51Skamil /* Fork again and drop parent to reattach to PID 1 */ 23491.51Skamil tracer = atf_utils_fork(); 23501.51Skamil if (tracer != 0) 23511.51Skamil _exit(exitval_tracer); 23521.51Skamil } 23531.51Skamil 23541.67Skamil if (stopped) { 23551.67Skamil DPRINTF("Await for a stopped parent PID %d\n", tracee); 23561.67Skamil await_stopped(tracee); 23571.67Skamil } 23581.67Skamil 23591.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 23601.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 23611.1Skamil 23621.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 23631.1Skamil FORKEE_REQUIRE_SUCCESS( 23641.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23651.1Skamil 23661.1Skamil forkee_status_stopped(status, SIGSTOP); 23671.1Skamil 23681.1Skamil /* Resume tracee with PT_CONTINUE */ 23691.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 23701.1Skamil 23711.1Skamil /* Inform parent that tracer has attached to tracee */ 23721.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 23731.1Skamil 23741.1Skamil /* Wait for parent to tell use that tracee should have exited */ 23751.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 23761.1Skamil 23771.1Skamil /* Wait for tracee and assert that it exited */ 23781.1Skamil FORKEE_REQUIRE_SUCCESS( 23791.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23801.1Skamil 23811.1Skamil forkee_status_exited(status, exitval_tracee); 23821.13Schristos DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee); 23831.1Skamil 23841.13Schristos DPRINTF("Before exiting of the tracer process\n"); 23851.51Skamil _exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer); 23861.51Skamil } 23871.51Skamil 23881.51Skamil if (unrelated) { 23891.51Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 23901.51Skamil "calling %s()\n", TWAIT_FNAME); 23911.51Skamil TWAIT_REQUIRE_SUCCESS( 23921.51Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 23931.51Skamil 23941.51Skamil validate_status_exited(status, exitval_tracer); 23951.51Skamil 23961.51Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 23971.51Skamil TWAIT_FNAME); 23981.51Skamil TWAIT_REQUIRE_SUCCESS( 23991.51Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 24001.1Skamil } 24011.1Skamil 24021.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 24031.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 24041.1Skamil 24051.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 24061.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 24071.1Skamil 24081.13Schristos DPRINTF("Detect that tracee is zombie\n"); 24091.51Skamil if (notimeout) 24101.26Skamil await_zombie_raw(tracee, 0); 24111.26Skamil else 24121.26Skamil await_zombie(tracee); 24131.1Skamil 24141.13Schristos DPRINTF("Assert that there is no status about tracee %d - " 24151.1Skamil "Tracer must detect zombie first - calling %s()\n", tracee, 24161.1Skamil TWAIT_FNAME); 24171.1Skamil TWAIT_REQUIRE_SUCCESS( 24181.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 24191.1Skamil 24201.51Skamil if (unrelated) { 24211.51Skamil DPRINTF("Resume the tracer and let it detect exited tracee\n"); 24221.51Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 24231.51Skamil } else { 24241.51Skamil DPRINTF("Tell the tracer child should have exited\n"); 24251.51Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 24261.51Skamil DPRINTF("Wait for tracer to finish its job and exit - calling " 24271.59Skamil "%s()\n", TWAIT_FNAME); 24281.51Skamil 24291.51Skamil DPRINTF("Wait from tracer child to complete waiting for " 24301.59Skamil "tracee\n"); 24311.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 24321.51Skamil tracer); 24331.1Skamil 24341.51Skamil validate_status_exited(status, exitval_tracer); 24351.51Skamil } 24361.1Skamil 24371.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 24381.1Skamil TWAIT_FNAME); 24391.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24401.1Skamil 24411.1Skamil validate_status_exited(status, exitval_tracee); 24421.1Skamil 24431.1Skamil msg_close(&parent_tracer); 24441.1Skamil msg_close(&parent_tracee); 24451.1Skamil} 24461.26Skamil 24471.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent); 24481.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc) 24491.51Skamil{ 24501.51Skamil atf_tc_set_md_var(tc, "descr", 24511.51Skamil "Assert that tracer sees process termination before the parent"); 24521.51Skamil} 24531.51Skamil 24541.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc) 24551.26Skamil{ 24561.26Skamil 24571.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, false, false); 24581.26Skamil} 24591.26Skamil 24601.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates); 24611.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc) 24621.1Skamil{ 24631.1Skamil atf_tc_set_md_var(tc, "descr", 24641.51Skamil "Assert that await_zombie() in attach1 always finds a single " 24651.51Skamil "process and no other error is reported"); 24661.1Skamil} 24671.1Skamil 24681.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc) 24691.1Skamil{ 24701.51Skamil time_t start, end; 24711.51Skamil double diff; 24721.51Skamil unsigned long N = 0; 24731.1Skamil 24741.51Skamil /* 24751.51Skamil * Reuse this test with tracer_sees_terminaton_before_the_parent_raw(). 24761.51Skamil * This test body isn't specific to this race, however it's just good 24771.51Skamil * enough for this purposes, no need to invent a dedicated code flow. 24781.51Skamil */ 24791.1Skamil 24801.51Skamil start = time(NULL); 24811.51Skamil while (true) { 24821.51Skamil DPRINTF("Step: %lu\n", N); 24831.67Skamil tracer_sees_terminaton_before_the_parent_raw(true, false, 24841.67Skamil false); 24851.51Skamil end = time(NULL); 24861.51Skamil diff = difftime(end, start); 24871.51Skamil if (diff >= 5.0) 24881.51Skamil break; 24891.51Skamil ++N; 24901.1Skamil } 24911.51Skamil DPRINTF("Iterations: %lu\n", N); 24921.51Skamil} 24931.1Skamil 24941.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent); 24951.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc) 24961.51Skamil{ 24971.51Skamil atf_tc_set_md_var(tc, "descr", 24981.51Skamil "Assert that tracer sees process termination before the parent"); 24991.51Skamil} 25001.1Skamil 25011.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc) 25021.51Skamil{ 25031.1Skamil 25041.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, false); 25051.67Skamil} 25061.67Skamil 25071.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process); 25081.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc) 25091.67Skamil{ 25101.67Skamil atf_tc_set_md_var(tc, "descr", 25111.67Skamil "Assert that tracer can attach to an unrelated stopped process"); 25121.67Skamil} 25131.67Skamil 25141.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc) 25151.67Skamil{ 25161.67Skamil 25171.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, true); 25181.1Skamil} 25191.1Skamil#endif 25201.1Skamil 25211.51Skamil/// ---------------------------------------------------------------------------- 25221.51Skamil 25231.66Skamilstatic void 25241.66Skamilparent_attach_to_its_child(bool stopped) 25251.1Skamil{ 25261.1Skamil struct msg_fds parent_tracee; 25271.1Skamil const int exitval_tracee = 5; 25281.1Skamil pid_t tracee, wpid; 25291.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 25301.1Skamil#if defined(TWAIT_HAVE_STATUS) 25311.1Skamil int status; 25321.1Skamil#endif 25331.1Skamil 25341.13Schristos DPRINTF("Spawn tracee\n"); 25351.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 25361.1Skamil tracee = atf_utils_fork(); 25371.1Skamil if (tracee == 0) { 25381.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 25391.13Schristos DPRINTF("Parent should now attach to tracee\n"); 25401.1Skamil 25411.66Skamil if (stopped) { 25421.66Skamil DPRINTF("Stop self PID %d\n", getpid()); 25431.66Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 25441.66Skamil } 25451.66Skamil 25461.1Skamil CHILD_FROM_PARENT("Message 2", parent_tracee, msg); 25471.1Skamil /* Wait for message from the parent */ 25481.1Skamil _exit(exitval_tracee); 25491.1Skamil } 25501.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 25511.57Skamil 25521.66Skamil if (stopped) { 25531.66Skamil DPRINTF("Await for a stopped tracee PID %d\n", tracee); 25541.66Skamil await_stopped(tracee); 25551.66Skamil } 25561.66Skamil 25571.13Schristos DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee); 25581.13Schristos SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 25591.1Skamil 25601.13Schristos DPRINTF("Wait for the stopped tracee process with %s()\n", 25611.1Skamil TWAIT_FNAME); 25621.1Skamil TWAIT_REQUIRE_SUCCESS( 25631.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25641.1Skamil 25651.1Skamil validate_status_stopped(status, SIGSTOP); 25661.1Skamil 25671.13Schristos DPRINTF("Resume tracee with PT_CONTINUE\n"); 25681.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 25691.1Skamil 25701.13Schristos DPRINTF("Let the tracee exit now\n"); 25711.1Skamil PARENT_TO_CHILD("Message 2", parent_tracee, msg); 25721.1Skamil 25731.13Schristos DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME); 25741.1Skamil TWAIT_REQUIRE_SUCCESS( 25751.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25761.1Skamil 25771.1Skamil validate_status_exited(status, exitval_tracee); 25781.1Skamil 25791.13Schristos DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME); 25801.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 25811.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0)); 25821.1Skamil 25831.1Skamil msg_close(&parent_tracee); 25841.1Skamil} 25851.1Skamil 25861.66SkamilATF_TC(parent_attach_to_its_child); 25871.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc) 25881.66Skamil{ 25891.66Skamil atf_tc_set_md_var(tc, "descr", 25901.66Skamil "Assert that tracer parent can PT_ATTACH to its child"); 25911.66Skamil} 25921.66Skamil 25931.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc) 25941.66Skamil{ 25951.66Skamil 25961.66Skamil parent_attach_to_its_child(false); 25971.66Skamil} 25981.66Skamil 25991.66SkamilATF_TC(parent_attach_to_its_stopped_child); 26001.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc) 26011.66Skamil{ 26021.66Skamil atf_tc_set_md_var(tc, "descr", 26031.66Skamil "Assert that tracer parent can PT_ATTACH to its stopped child"); 26041.66Skamil} 26051.66Skamil 26061.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc) 26071.66Skamil{ 26081.66Skamil 26091.66Skamil parent_attach_to_its_child(true); 26101.66Skamil} 26111.66Skamil 26121.51Skamil/// ---------------------------------------------------------------------------- 26131.51Skamil 26141.65Skamilstatic void 26151.65Skamilchild_attach_to_its_parent(bool stopped) 26161.1Skamil{ 26171.1Skamil struct msg_fds parent_tracee; 26181.1Skamil const int exitval_tracer = 5; 26191.1Skamil pid_t tracer, wpid; 26201.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 26211.1Skamil#if defined(TWAIT_HAVE_STATUS) 26221.1Skamil int status; 26231.1Skamil#endif 26241.1Skamil 26251.13Schristos DPRINTF("Spawn tracer\n"); 26261.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 26271.1Skamil tracer = atf_utils_fork(); 26281.1Skamil if (tracer == 0) { 26291.1Skamil /* Wait for message from the parent */ 26301.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 26311.1Skamil 26321.65Skamil if (stopped) { 26331.65Skamil DPRINTF("Await for a stopped parent PID %d\n", 26341.65Skamil getppid()); 26351.65Skamil await_stopped(getppid()); 26361.65Skamil } 26371.65Skamil 26381.13Schristos DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n", 26391.1Skamil getppid()); 26401.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1); 26411.1Skamil 26421.13Schristos DPRINTF("Wait for the stopped parent process with %s()\n", 26431.1Skamil TWAIT_FNAME); 26441.1Skamil FORKEE_REQUIRE_SUCCESS( 26451.1Skamil wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid()); 26461.1Skamil 26471.1Skamil forkee_status_stopped(status, SIGSTOP); 26481.1Skamil 26491.13Schristos DPRINTF("Resume parent with PT_DETACH\n"); 26501.1Skamil FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0) 26511.1Skamil != -1); 26521.1Skamil 26531.1Skamil /* Tell parent we are ready */ 26541.1Skamil CHILD_TO_PARENT("Message 1", parent_tracee, msg); 26551.1Skamil 26561.1Skamil _exit(exitval_tracer); 26571.1Skamil } 26581.1Skamil 26591.13Schristos DPRINTF("Wait for the tracer to become ready\n"); 26601.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 26611.65Skamil 26621.65Skamil if (stopped) { 26631.65Skamil DPRINTF("Stop self PID %d\n", getpid()); 26641.65Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 26651.65Skamil } 26661.65Skamil 26671.13Schristos DPRINTF("Allow the tracer to exit now\n"); 26681.1Skamil PARENT_FROM_CHILD("Message 1", parent_tracee, msg); 26691.1Skamil 26701.13Schristos DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME); 26711.1Skamil TWAIT_REQUIRE_SUCCESS( 26721.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 26731.1Skamil 26741.1Skamil validate_status_exited(status, exitval_tracer); 26751.1Skamil 26761.13Schristos DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME); 26771.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 26781.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0)); 26791.1Skamil 26801.1Skamil msg_close(&parent_tracee); 26811.1Skamil} 26821.1Skamil 26831.65SkamilATF_TC(child_attach_to_its_parent); 26841.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc) 26851.65Skamil{ 26861.65Skamil atf_tc_set_md_var(tc, "descr", 26871.65Skamil "Assert that tracer child can PT_ATTACH to its parent"); 26881.65Skamil} 26891.65Skamil 26901.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc) 26911.65Skamil{ 26921.65Skamil 26931.65Skamil child_attach_to_its_parent(false); 26941.65Skamil} 26951.65Skamil 26961.65SkamilATF_TC(child_attach_to_its_stopped_parent); 26971.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc) 26981.65Skamil{ 26991.65Skamil atf_tc_set_md_var(tc, "descr", 27001.65Skamil "Assert that tracer child can PT_ATTACH to its stopped parent"); 27011.65Skamil} 27021.65Skamil 27031.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc) 27041.65Skamil{ 27051.65Skamil /* 27061.65Skamil * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as 27071.65Skamil * this causes a pipe (established from atf-run) to be broken. 27081.65Skamil * atf-run uses this mechanism to monitor whether a test is alive. 27091.65Skamil * 27101.65Skamil * As a workaround spawn this test as a subprocess. 27111.65Skamil */ 27121.65Skamil 27131.65Skamil const int exitval = 15; 27141.65Skamil pid_t child, wpid; 27151.65Skamil#if defined(TWAIT_HAVE_STATUS) 27161.65Skamil int status; 27171.65Skamil#endif 27181.65Skamil 27191.65Skamil SYSCALL_REQUIRE((child = fork()) != -1); 27201.65Skamil if (child == 0) { 27211.65Skamil child_attach_to_its_parent(true); 27221.65Skamil _exit(exitval); 27231.65Skamil } else { 27241.65Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 27251.65Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 27261.65Skamil 27271.65Skamil validate_status_exited(status, exitval); 27281.65Skamil 27291.65Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 27301.65Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 27311.65Skamil } 27321.65Skamil} 27331.65Skamil 27341.51Skamil/// ---------------------------------------------------------------------------- 27351.51Skamil 27361.1Skamil#if defined(TWAIT_HAVE_PID) 27371.1Skamil 27381.51Skamilenum tracee_sees_its_original_parent_type { 27391.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 27401.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 27411.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS 27421.51Skamil}; 27431.51Skamil 27441.51Skamilstatic void 27451.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type) 27461.1Skamil{ 27471.1Skamil struct msg_fds parent_tracer, parent_tracee; 27481.1Skamil const int exitval_tracee = 5; 27491.1Skamil const int exitval_tracer = 10; 27501.1Skamil pid_t parent, tracee, tracer, wpid; 27511.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 27521.1Skamil#if defined(TWAIT_HAVE_STATUS) 27531.1Skamil int status; 27541.1Skamil#endif 27551.51Skamil /* sysctl(3) - kinfo_proc2 */ 27561.51Skamil int name[CTL_MAXNAME]; 27571.51Skamil struct kinfo_proc2 kp; 27581.51Skamil size_t len = sizeof(kp); 27591.51Skamil unsigned int namelen; 27601.51Skamil 27611.51Skamil /* procfs - status */ 27621.51Skamil FILE *fp; 27631.51Skamil struct stat st; 27641.51Skamil const char *fname = "/proc/curproc/status"; 27651.51Skamil char s_executable[MAXPATHLEN]; 27661.51Skamil int s_pid, s_ppid; 27671.51Skamil int rv; 27681.51Skamil 27691.51Skamil if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) { 27701.61Skre SYSCALL_REQUIRE( 27711.61Skre (rv = stat(fname, &st)) == 0 || (errno == ENOENT)); 27721.61Skre if (rv != 0) 27731.51Skamil atf_tc_skip("/proc/curproc/status not found"); 27741.51Skamil } 27751.1Skamil 27761.13Schristos DPRINTF("Spawn tracee\n"); 27771.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 27781.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 27791.1Skamil tracee = atf_utils_fork(); 27801.1Skamil if (tracee == 0) { 27811.1Skamil parent = getppid(); 27821.1Skamil 27831.1Skamil /* Emit message to the parent */ 27841.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 27851.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 27861.1Skamil 27871.51Skamil switch (type) { 27881.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID: 27891.51Skamil FORKEE_ASSERT_EQ(parent, getppid()); 27901.51Skamil break; 27911.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2: 27921.51Skamil namelen = 0; 27931.51Skamil name[namelen++] = CTL_KERN; 27941.51Skamil name[namelen++] = KERN_PROC2; 27951.51Skamil name[namelen++] = KERN_PROC_PID; 27961.51Skamil name[namelen++] = getpid(); 27971.51Skamil name[namelen++] = len; 27981.51Skamil name[namelen++] = 1; 27991.51Skamil 28001.61Skre FORKEE_ASSERT_EQ( 28011.61Skre sysctl(name, namelen, &kp, &len, NULL, 0), 0); 28021.51Skamil FORKEE_ASSERT_EQ(parent, kp.p_ppid); 28031.51Skamil break; 28041.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS: 28051.51Skamil /* 28061.51Skamil * Format: 28071.51Skamil * EXECUTABLE PID PPID ... 28081.51Skamil */ 28091.51Skamil FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL); 28101.51Skamil fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid); 28111.51Skamil FORKEE_ASSERT_EQ(fclose(fp), 0); 28121.51Skamil FORKEE_ASSERT_EQ(parent, s_ppid); 28131.51Skamil break; 28141.51Skamil } 28151.1Skamil 28161.1Skamil _exit(exitval_tracee); 28171.1Skamil } 28181.13Schristos DPRINTF("Wait for child to record its parent identifier (pid)\n"); 28191.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 28201.1Skamil 28211.13Schristos DPRINTF("Spawn debugger\n"); 28221.1Skamil tracer = atf_utils_fork(); 28231.1Skamil if (tracer == 0) { 28241.1Skamil /* No IPC to communicate with the child */ 28251.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 28261.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 28271.1Skamil 28281.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 28291.1Skamil FORKEE_REQUIRE_SUCCESS( 28301.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28311.1Skamil 28321.1Skamil forkee_status_stopped(status, SIGSTOP); 28331.1Skamil 28341.1Skamil /* Resume tracee with PT_CONTINUE */ 28351.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 28361.1Skamil 28371.1Skamil /* Inform parent that tracer has attached to tracee */ 28381.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 28391.1Skamil 28401.1Skamil /* Wait for parent to tell use that tracee should have exited */ 28411.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 28421.1Skamil 28431.1Skamil /* Wait for tracee and assert that it exited */ 28441.1Skamil FORKEE_REQUIRE_SUCCESS( 28451.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28461.1Skamil 28471.1Skamil forkee_status_exited(status, exitval_tracee); 28481.1Skamil 28491.13Schristos DPRINTF("Before exiting of the tracer process\n"); 28501.1Skamil _exit(exitval_tracer); 28511.1Skamil } 28521.1Skamil 28531.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 28541.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 28551.1Skamil 28561.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 28571.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 28581.1Skamil 28591.13Schristos DPRINTF("Detect that tracee is zombie\n"); 28601.1Skamil await_zombie(tracee); 28611.1Skamil 28621.13Schristos DPRINTF("Assert that there is no status about tracee - " 28631.1Skamil "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME); 28641.1Skamil TWAIT_REQUIRE_SUCCESS( 28651.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 28661.1Skamil 28671.13Schristos DPRINTF("Tell the tracer child should have exited\n"); 28681.1Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 28691.1Skamil 28701.13Schristos DPRINTF("Wait from tracer child to complete waiting for tracee\n"); 28711.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 28721.1Skamil tracer); 28731.1Skamil 28741.1Skamil validate_status_exited(status, exitval_tracer); 28751.1Skamil 28761.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 28771.1Skamil TWAIT_FNAME); 28781.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 28791.1Skamil tracee); 28801.1Skamil 28811.1Skamil validate_status_exited(status, exitval_tracee); 28821.1Skamil 28831.1Skamil msg_close(&parent_tracer); 28841.1Skamil msg_close(&parent_tracee); 28851.1Skamil} 28861.1Skamil 28871.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr) \ 28881.61SkreATF_TC(test); \ 28891.61SkreATF_TC_HEAD(test, tc) \ 28901.61Skre{ \ 28911.61Skre atf_tc_set_md_var(tc, "descr", \ 28921.61Skre "Assert that tracee sees its original parent when being traced " \ 28931.61Skre "(check " descr ")"); \ 28941.61Skre} \ 28951.61Skre \ 28961.61SkreATF_TC_BODY(test, tc) \ 28971.61Skre{ \ 28981.61Skre \ 28991.61Skre tracee_sees_its_original_parent(type); \ 29001.1Skamil} 29011.1Skamil 29021.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29031.51Skamil tracee_sees_its_original_parent_getppid, 29041.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 29051.51Skamil "getppid(2)"); 29061.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29071.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2, 29081.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 29091.51Skamil "sysctl(3) and kinfo_proc2"); 29101.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29111.51Skamil tracee_sees_its_original_parent_procfs_status, 29121.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS, 29131.51Skamil "the status file in procfs"); 29141.1Skamil#endif 29151.1Skamil 29161.51Skamil/// ---------------------------------------------------------------------------- 29171.1Skamil 29181.53Skamilstatic void 29191.53Skamileventmask_preserved(int event) 29201.1Skamil{ 29211.1Skamil const int exitval = 5; 29221.1Skamil const int sigval = SIGSTOP; 29231.1Skamil pid_t child, wpid; 29241.1Skamil#if defined(TWAIT_HAVE_STATUS) 29251.1Skamil int status; 29261.1Skamil#endif 29271.1Skamil ptrace_event_t set_event, get_event; 29281.1Skamil const int len = sizeof(ptrace_event_t); 29291.1Skamil 29301.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 29311.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 29321.1Skamil if (child == 0) { 29331.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 29341.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 29351.1Skamil 29361.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 29371.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 29381.1Skamil 29391.13Schristos DPRINTF("Before exiting of the child process\n"); 29401.1Skamil _exit(exitval); 29411.1Skamil } 29421.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 29431.1Skamil 29441.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29451.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29461.1Skamil 29471.1Skamil validate_status_stopped(status, sigval); 29481.1Skamil 29491.53Skamil set_event.pe_set_event = event; 29501.61Skre SYSCALL_REQUIRE( 29511.61Skre ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); 29521.61Skre SYSCALL_REQUIRE( 29531.61Skre ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); 29541.125Skamil DPRINTF("set_event=%#x get_event=%#x\n", set_event.pe_set_event, 29551.125Skamil get_event.pe_set_event); 29561.1Skamil ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); 29571.1Skamil 29581.13Schristos DPRINTF("Before resuming the child process where it left off and " 29591.1Skamil "without signal to be sent\n"); 29601.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 29611.1Skamil 29621.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29631.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29641.1Skamil 29651.1Skamil validate_status_exited(status, exitval); 29661.1Skamil 29671.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29681.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 29691.1Skamil} 29701.1Skamil 29711.61Skre#define EVENTMASK_PRESERVED(test, event) \ 29721.61SkreATF_TC(test); \ 29731.61SkreATF_TC_HEAD(test, tc) \ 29741.61Skre{ \ 29751.61Skre atf_tc_set_md_var(tc, "descr", \ 29761.61Skre "Verify that eventmask " #event " is preserved"); \ 29771.61Skre} \ 29781.61Skre \ 29791.61SkreATF_TC_BODY(test, tc) \ 29801.61Skre{ \ 29811.61Skre \ 29821.61Skre eventmask_preserved(event); \ 29831.1Skamil} 29841.1Skamil 29851.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0) 29861.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK) 29871.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK) 29881.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE) 29891.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE) 29901.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT) 29911.125SkamilEVENTMASK_PRESERVED(eventmask_preserved_posix_spawn, PTRACE_POSIX_SPAWN) 29921.1Skamil 29931.53Skamil/// ---------------------------------------------------------------------------- 29941.1Skamil 29951.28Skamilstatic void 29961.125Skamilfork_body(const char *fn, bool trackspawn, bool trackfork, bool trackvfork, 29971.105Skamil bool trackvforkdone) 29981.1Skamil{ 29991.1Skamil const int exitval = 5; 30001.125Skamil const int exitval2 = 0; /* This matched exit status from /bin/echo */ 30011.1Skamil const int sigval = SIGSTOP; 30021.31Skamil pid_t child, child2 = 0, wpid; 30031.1Skamil#if defined(TWAIT_HAVE_STATUS) 30041.1Skamil int status; 30051.1Skamil#endif 30061.1Skamil ptrace_state_t state; 30071.1Skamil const int slen = sizeof(state); 30081.1Skamil ptrace_event_t event; 30091.1Skamil const int elen = sizeof(event); 30101.1Skamil 30111.124Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 30121.124Skamil 30131.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 30141.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 30151.1Skamil if (child == 0) { 30161.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 30171.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 30181.1Skamil 30191.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 30201.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 30211.1Skamil 30221.125Skamil if (strcmp(fn, "spawn") == 0) { 30231.124Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 30241.124Skamil arg[0], NULL, NULL, arg, NULL), 0); 30251.125Skamil } else { 30261.125Skamil if (strcmp(fn, "fork") == 0) { 30271.125Skamil FORKEE_ASSERT((child2 = fork()) != -1); 30281.125Skamil } else if (strcmp(fn, "vfork") == 0) { 30291.125Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 30301.125Skamil } 30311.1Skamil 30321.124Skamil if (child2 == 0) 30331.124Skamil _exit(exitval2); 30341.124Skamil } 30351.1Skamil FORKEE_REQUIRE_SUCCESS 30361.1Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 30371.1Skamil 30381.1Skamil forkee_status_exited(status, exitval2); 30391.1Skamil 30401.13Schristos DPRINTF("Before exiting of the child process\n"); 30411.1Skamil _exit(exitval); 30421.1Skamil } 30431.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 30441.1Skamil 30451.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 30461.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 30471.1Skamil 30481.1Skamil validate_status_stopped(status, sigval); 30491.1Skamil 30501.125Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 30511.125Skamil trackspawn ? "|PTRACE_POSIX_SPAWN" : "", 30521.61Skre trackfork ? "|PTRACE_FORK" : "", 30531.61Skre trackvfork ? "|PTRACE_VFORK" : "", 30541.61Skre trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 30551.30Skamil event.pe_set_event = 0; 30561.125Skamil if (trackspawn) 30571.125Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 30581.30Skamil if (trackfork) 30591.30Skamil event.pe_set_event |= PTRACE_FORK; 30601.30Skamil if (trackvfork) 30611.30Skamil event.pe_set_event |= PTRACE_VFORK; 30621.30Skamil if (trackvforkdone) 30631.30Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 30641.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 30651.1Skamil 30661.13Schristos DPRINTF("Before resuming the child process where it left off and " 30671.1Skamil "without signal to be sent\n"); 30681.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 30691.1Skamil 30701.29Skamil#if defined(TWAIT_HAVE_PID) 30711.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 30721.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 30731.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 30741.29Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 30751.61Skre child); 30761.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 30771.61Skre child); 30781.1Skamil 30791.29Skamil validate_status_stopped(status, SIGTRAP); 30801.1Skamil 30811.61Skre SYSCALL_REQUIRE( 30821.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 30831.125Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 30841.125Skamil ATF_REQUIRE_EQ( 30851.125Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 30861.125Skamil PTRACE_POSIX_SPAWN); 30871.125Skamil } 30881.125Skamil if (trackfork && strcmp(fn, "fork") == 0) { 30891.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 30901.30Skamil PTRACE_FORK); 30911.30Skamil } 30921.125Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 30931.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 30941.30Skamil PTRACE_VFORK); 30951.30Skamil } 30961.29Skamil 30971.29Skamil child2 = state.pe_other_pid; 30981.30Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 30991.29Skamil 31001.29Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 31011.61Skre "%d\n", TWAIT_FNAME, child2, child); 31021.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 31031.29Skamil child2); 31041.1Skamil 31051.29Skamil validate_status_stopped(status, SIGTRAP); 31061.1Skamil 31071.61Skre SYSCALL_REQUIRE( 31081.61Skre ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 31091.125Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 31101.125Skamil ATF_REQUIRE_EQ( 31111.125Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 31121.125Skamil PTRACE_POSIX_SPAWN); 31131.125Skamil } 31141.125Skamil if (trackfork && strcmp(fn, "fork") == 0) { 31151.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 31161.30Skamil PTRACE_FORK); 31171.30Skamil } 31181.125Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 31191.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 31201.30Skamil PTRACE_VFORK); 31211.30Skamil } 31221.30Skamil 31231.29Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 31241.29Skamil 31251.29Skamil DPRINTF("Before resuming the forkee process where it left off " 31261.29Skamil "and without signal to be sent\n"); 31271.61Skre SYSCALL_REQUIRE( 31281.61Skre ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 31291.29Skamil 31301.29Skamil DPRINTF("Before resuming the child process where it left off " 31311.61Skre "and without signal to be sent\n"); 31321.29Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31331.30Skamil } 31341.30Skamil#endif 31351.30Skamil 31361.125Skamil if (trackvforkdone && strcmp(fn, "vfork") == 0) { 31371.30Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 31381.61Skre child); 31391.61Skre TWAIT_REQUIRE_SUCCESS( 31401.61Skre wpid = TWAIT_GENERIC(child, &status, 0), child); 31411.30Skamil 31421.30Skamil validate_status_stopped(status, SIGTRAP); 31431.30Skamil 31441.61Skre SYSCALL_REQUIRE( 31451.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 31461.30Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 31471.30Skamil 31481.30Skamil child2 = state.pe_other_pid; 31491.30Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 31501.61Skre child2); 31511.30Skamil 31521.30Skamil DPRINTF("Before resuming the child process where it left off " 31531.61Skre "and without signal to be sent\n"); 31541.30Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31551.30Skamil } 31561.29Skamil 31571.30Skamil#if defined(TWAIT_HAVE_PID) 31581.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 31591.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 31601.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 31611.29Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 31621.61Skre "\n", TWAIT_FNAME); 31631.61Skre TWAIT_REQUIRE_SUCCESS( 31641.61Skre wpid = TWAIT_GENERIC(child2, &status, 0), child2); 31651.29Skamil 31661.29Skamil validate_status_exited(status, exitval2); 31671.29Skamil 31681.29Skamil DPRINTF("Before calling %s() for the forkee - expected no " 31691.61Skre "process\n", TWAIT_FNAME); 31701.29Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 31711.29Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 31721.29Skamil } 31731.29Skamil#endif 31741.1Skamil 31751.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 31761.1Skamil "SIGCHLD\n", TWAIT_FNAME); 31771.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31781.1Skamil 31791.1Skamil validate_status_stopped(status, SIGCHLD); 31801.1Skamil 31811.13Schristos DPRINTF("Before resuming the child process where it left off and " 31821.1Skamil "without signal to be sent\n"); 31831.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31841.1Skamil 31851.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 31861.1Skamil TWAIT_FNAME); 31871.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31881.1Skamil 31891.1Skamil validate_status_exited(status, exitval); 31901.1Skamil 31911.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 31921.1Skamil TWAIT_FNAME); 31931.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 31941.1Skamil} 31951.28Skamil 31961.125Skamil#define FORK_TEST(name,fun,tspawn,tfork,tvfork,tvforkdone) \ 31971.61SkreATF_TC(name); \ 31981.61SkreATF_TC_HEAD(name, tc) \ 31991.61Skre{ \ 32001.125Skamil atf_tc_set_md_var(tc, "descr", "Verify " fun "() " \ 32011.125Skamil "called with 0%s%s%s%s in EVENT_MASK", \ 32021.126Skamil tspawn ? "|PTRACE_POSIX_SPAWN" : "", \ 32031.105Skamil tfork ? "|PTRACE_FORK" : "", \ 32041.105Skamil tvfork ? "|PTRACE_VFORK" : "", \ 32051.105Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 32061.61Skre} \ 32071.61Skre \ 32081.61SkreATF_TC_BODY(name, tc) \ 32091.61Skre{ \ 32101.61Skre \ 32111.125Skamil fork_body(fun, tspawn, tfork, tvfork, tvforkdone); \ 32121.32Skamil} 32131.32Skamil 32141.125SkamilFORK_TEST(fork1, "fork", false, false, false, false) 32151.31Skamil#if defined(TWAIT_HAVE_PID) 32161.125SkamilFORK_TEST(fork2, "fork", false, true, false, false) 32171.125SkamilFORK_TEST(fork3, "fork", false, false, true, false) 32181.125SkamilFORK_TEST(fork4, "fork", false, true, true, false) 32191.31Skamil#endif 32201.125SkamilFORK_TEST(fork5, "fork", false, false, false, true) 32211.31Skamil#if defined(TWAIT_HAVE_PID) 32221.125SkamilFORK_TEST(fork6, "fork", false, true, false, true) 32231.125SkamilFORK_TEST(fork7, "fork", false, false, true, true) 32241.125SkamilFORK_TEST(fork8, "fork", false, true, true, true) 32251.125Skamil#endif 32261.125SkamilFORK_TEST(fork9, "fork", true, false, false, false) 32271.125Skamil#if defined(TWAIT_HAVE_PID) 32281.125SkamilFORK_TEST(fork10, "fork", true, true, false, false) 32291.125SkamilFORK_TEST(fork11, "fork", true, false, true, false) 32301.125SkamilFORK_TEST(fork12, "fork", true, true, true, false) 32311.125Skamil#endif 32321.125SkamilFORK_TEST(fork13, "fork", true, false, false, true) 32331.125Skamil#if defined(TWAIT_HAVE_PID) 32341.125SkamilFORK_TEST(fork14, "fork", true, true, false, true) 32351.125SkamilFORK_TEST(fork15, "fork", true, false, true, true) 32361.125SkamilFORK_TEST(fork16, "fork", true, true, true, true) 32371.31Skamil#endif 32381.1Skamil 32391.110Skamil#if TEST_VFORK_ENABLED 32401.125SkamilFORK_TEST(vfork1, "vfork", false, false, false, false) 32411.31Skamil#if defined(TWAIT_HAVE_PID) 32421.125SkamilFORK_TEST(vfork2, "vfork", false, true, false, false) 32431.125SkamilFORK_TEST(vfork3, "vfork", false, false, true, false) 32441.125SkamilFORK_TEST(vfork4, "vfork", false, true, true, false) 32451.31Skamil#endif 32461.125SkamilFORK_TEST(vfork5, "vfork", false, false, false, true) 32471.31Skamil#if defined(TWAIT_HAVE_PID) 32481.125SkamilFORK_TEST(vfork6, "vfork", false, true, false, true) 32491.125SkamilFORK_TEST(vfork7, "vfork", false, false, true, true) 32501.125SkamilFORK_TEST(vfork8, "vfork", false, true, true, true) 32511.31Skamil#endif 32521.125SkamilFORK_TEST(vfork9, "vfork", true, false, false, false) 32531.125Skamil#if defined(TWAIT_HAVE_PID) 32541.125SkamilFORK_TEST(vfork10, "vfork", true, true, false, false) 32551.125SkamilFORK_TEST(vfork11, "vfork", true, false, true, false) 32561.125SkamilFORK_TEST(vfork12, "vfork", true, true, true, false) 32571.110Skamil#endif 32581.125SkamilFORK_TEST(vfork13, "vfork", true, false, false, true) 32591.124Skamil#if defined(TWAIT_HAVE_PID) 32601.125SkamilFORK_TEST(vfork14, "vfork", true, true, false, true) 32611.125SkamilFORK_TEST(vfork15, "vfork", true, false, true, true) 32621.125SkamilFORK_TEST(vfork16, "vfork", true, true, true, true) 32631.124Skamil#endif 32641.125Skamil#endif 32651.125Skamil 32661.125SkamilFORK_TEST(posix_spawn1, "spawn", false, false, false, false) 32671.125SkamilFORK_TEST(posix_spawn2, "spawn", false, true, false, false) 32681.125SkamilFORK_TEST(posix_spawn3, "spawn", false, false, true, false) 32691.125SkamilFORK_TEST(posix_spawn4, "spawn", false, true, true, false) 32701.125SkamilFORK_TEST(posix_spawn5, "spawn", false, false, false, true) 32711.125SkamilFORK_TEST(posix_spawn6, "spawn", false, true, false, true) 32721.125SkamilFORK_TEST(posix_spawn7, "spawn", false, false, true, true) 32731.125SkamilFORK_TEST(posix_spawn8, "spawn", false, true, true, true) 32741.124Skamil#if defined(TWAIT_HAVE_PID) 32751.125SkamilFORK_TEST(posix_spawn9, "spawn", true, false, false, false) 32761.125SkamilFORK_TEST(posix_spawn10, "spawn", true, true, false, false) 32771.125SkamilFORK_TEST(posix_spawn11, "spawn", true, false, true, false) 32781.125SkamilFORK_TEST(posix_spawn12, "spawn", true, true, true, false) 32791.125SkamilFORK_TEST(posix_spawn13, "spawn", true, false, false, true) 32801.125SkamilFORK_TEST(posix_spawn14, "spawn", true, true, false, true) 32811.125SkamilFORK_TEST(posix_spawn15, "spawn", true, false, true, true) 32821.125SkamilFORK_TEST(posix_spawn16, "spawn", true, true, true, true) 32831.124Skamil#endif 32841.124Skamil 32851.54Skamil/// ---------------------------------------------------------------------------- 32861.31Skamil 32871.116Skamil#if defined(TWAIT_HAVE_PID) 32881.116Skamilstatic void 32891.126Skamilfork_detach_forker_body(const char *fn, bool kill_process) 32901.116Skamil{ 32911.116Skamil const int exitval = 5; 32921.126Skamil const int exitval2 = 0; /* Matches exit value from /bin/echo */ 32931.116Skamil const int sigval = SIGSTOP; 32941.116Skamil pid_t child, child2 = 0, wpid; 32951.116Skamil#if defined(TWAIT_HAVE_STATUS) 32961.116Skamil int status; 32971.116Skamil#endif 32981.116Skamil ptrace_state_t state; 32991.116Skamil const int slen = sizeof(state); 33001.116Skamil ptrace_event_t event; 33011.116Skamil const int elen = sizeof(event); 33021.116Skamil 33031.116Skamil int op; 33041.116Skamil 33051.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 33061.116Skamil 33071.116Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 33081.116Skamil SYSCALL_REQUIRE((child = fork()) != -1); 33091.116Skamil if (child == 0) { 33101.116Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 33111.116Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 33121.116Skamil 33131.116Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 33141.116Skamil FORKEE_ASSERT(raise(sigval) == 0); 33151.116Skamil 33161.126Skamil if (strcmp(fn, "spawn") == 0) { 33171.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 33181.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 33191.126Skamil } else { 33201.126Skamil if (strcmp(fn, "fork") == 0) { 33211.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 33221.126Skamil } else { 33231.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 33241.126Skamil } 33251.116Skamil 33261.126Skamil if (child2 == 0) 33271.126Skamil _exit(exitval2); 33281.126Skamil } 33291.116Skamil 33301.116Skamil FORKEE_REQUIRE_SUCCESS 33311.116Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 33321.116Skamil 33331.116Skamil forkee_status_exited(status, exitval2); 33341.116Skamil 33351.116Skamil DPRINTF("Before exiting of the child process\n"); 33361.116Skamil _exit(exitval); 33371.116Skamil } 33381.116Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 33391.116Skamil 33401.116Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 33411.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33421.116Skamil 33431.116Skamil validate_status_stopped(status, sigval); 33441.116Skamil 33451.116Skamil DPRINTF("Set EVENT_MASK for the child %d\n", child); 33461.126Skamil event.pe_set_event = PTRACE_POSIX_SPAWN | PTRACE_FORK | PTRACE_VFORK 33471.126Skamil | PTRACE_VFORK_DONE; 33481.116Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 33491.116Skamil 33501.116Skamil DPRINTF("Before resuming the child process where it left off and " 33511.116Skamil "without signal to be sent\n"); 33521.116Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 33531.116Skamil 33541.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child); 33551.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33561.116Skamil 33571.116Skamil validate_status_stopped(status, SIGTRAP); 33581.116Skamil 33591.116Skamil SYSCALL_REQUIRE( 33601.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 33611.126Skamil 33621.126Skamil if (strcmp(fn, "spawn") == 0) 33631.126Skamil op = PTRACE_POSIX_SPAWN; 33641.126Skamil else if (strcmp(fn, "fork") == 0) 33651.126Skamil op = PTRACE_FORK; 33661.126Skamil else 33671.126Skamil op = PTRACE_VFORK; 33681.126Skamil 33691.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 33701.116Skamil 33711.116Skamil child2 = state.pe_other_pid; 33721.116Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 33731.116Skamil 33741.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 33751.126Skamil strcmp(fn, "vfork") == 0) 33761.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 33771.116Skamil else 33781.116Skamil op = PT_CONTINUE; 33791.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 33801.116Skamil 33811.116Skamil DPRINTF("Before calling %s() for the forkee %d of the child %d\n", 33821.116Skamil TWAIT_FNAME, child2, child); 33831.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 33841.116Skamil 33851.116Skamil validate_status_stopped(status, SIGTRAP); 33861.116Skamil 33871.116Skamil SYSCALL_REQUIRE( 33881.116Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 33891.126Skamil if (strcmp(fn, "spawn") == 0) 33901.126Skamil op = PTRACE_POSIX_SPAWN; 33911.126Skamil else if (strcmp(fn, "fork") == 0) 33921.126Skamil op = PTRACE_FORK; 33931.126Skamil else 33941.126Skamil op = PTRACE_VFORK; 33951.126Skamil 33961.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 33971.116Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 33981.116Skamil 33991.116Skamil DPRINTF("Before resuming the forkee process where it left off " 34001.116Skamil "and without signal to be sent\n"); 34011.116Skamil SYSCALL_REQUIRE( 34021.116Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 34031.116Skamil 34041.126Skamil if (strcmp(fn, "vforkdone") == 0) { 34051.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 34061.116Skamil child); 34071.116Skamil TWAIT_REQUIRE_SUCCESS( 34081.116Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 34091.116Skamil 34101.116Skamil validate_status_stopped(status, SIGTRAP); 34111.116Skamil 34121.116Skamil SYSCALL_REQUIRE( 34131.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 34141.116Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 34151.116Skamil 34161.116Skamil child2 = state.pe_other_pid; 34171.116Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 34181.116Skamil child2); 34191.116Skamil 34201.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 34211.116Skamil DPRINTF("Before resuming the child process where it left off " 34221.116Skamil "and without signal to be sent\n"); 34231.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 34241.116Skamil } 34251.116Skamil 34261.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 34271.116Skamil TWAIT_FNAME); 34281.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 34291.116Skamil 34301.116Skamil validate_status_exited(status, exitval2); 34311.116Skamil 34321.116Skamil DPRINTF("Before calling %s() for the forkee - expected no process\n", 34331.116Skamil TWAIT_FNAME); 34341.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child2, &status, 0)); 34351.116Skamil 34361.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 34371.116Skamil TWAIT_FNAME); 34381.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 34391.116Skamil 34401.116Skamil if (kill_process) { 34411.116Skamil validate_status_signaled(status, SIGKILL, 0); 34421.116Skamil } else { 34431.116Skamil validate_status_exited(status, exitval); 34441.116Skamil } 34451.116Skamil 34461.116Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 34471.116Skamil TWAIT_FNAME); 34481.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 34491.116Skamil} 34501.116Skamil 34511.126Skamil#define FORK_DETACH_FORKER(name,event,kprocess) \ 34521.116SkamilATF_TC(name); \ 34531.116SkamilATF_TC_HEAD(name, tc) \ 34541.116Skamil{ \ 34551.126Skamil atf_tc_set_md_var(tc, "descr", "Verify %s " event, \ 34561.126Skamil kprocess ? "killed" : "detached"); \ 34571.116Skamil} \ 34581.116Skamil \ 34591.116SkamilATF_TC_BODY(name, tc) \ 34601.116Skamil{ \ 34611.116Skamil \ 34621.126Skamil fork_detach_forker_body(event, kprocess); \ 34631.116Skamil} 34641.116Skamil 34651.126SkamilFORK_DETACH_FORKER(posix_spawn_detach_spawner, "spawn", false) 34661.126SkamilFORK_DETACH_FORKER(fork_detach_forker, "fork", false) 34671.116Skamil#if TEST_VFORK_ENABLED 34681.126SkamilFORK_DETACH_FORKER(vfork_detach_vforker, "vfork", false) 34691.126SkamilFORK_DETACH_FORKER(vfork_detach_vforkerdone, "vforkdone", false) 34701.116Skamil#endif 34711.126Skamil 34721.126SkamilFORK_DETACH_FORKER(posix_spawn_kill_spawner, "spawn", true) 34731.126SkamilFORK_DETACH_FORKER(fork_kill_forker, "fork", true) 34741.116Skamil#if TEST_VFORK_ENABLED 34751.126SkamilFORK_DETACH_FORKER(vfork_kill_vforker, "vfork", true) 34761.126SkamilFORK_DETACH_FORKER(vfork_kill_vforkerdone, "vforkdone", true) 34771.116Skamil#endif 34781.116Skamil#endif 34791.116Skamil 34801.116Skamil/// ---------------------------------------------------------------------------- 34811.116Skamil 34821.110Skamil#if TEST_VFORK_ENABLED 34831.108Skamilstatic void 34841.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void)) 34851.108Skamil{ 34861.108Skamil const int exitval = 5; 34871.108Skamil const int exitval2 = 15; 34881.108Skamil pid_t child, child2 = 0, wpid; 34891.108Skamil#if defined(TWAIT_HAVE_STATUS) 34901.108Skamil int status; 34911.108Skamil#endif 34921.108Skamil 34931.108Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 34941.108Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 34951.108Skamil if (child == 0) { 34961.108Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 34971.108Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 34981.108Skamil 34991.108Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 35001.108Skamil 35011.108Skamil if (child2 == 0) 35021.108Skamil _exit(exitval2); 35031.108Skamil 35041.108Skamil FORKEE_REQUIRE_SUCCESS 35051.108Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 35061.108Skamil 35071.108Skamil forkee_status_exited(status, exitval2); 35081.108Skamil 35091.108Skamil DPRINTF("Before exiting of the child process\n"); 35101.108Skamil _exit(exitval); 35111.108Skamil } 35121.108Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 35131.108Skamil 35141.108Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 35151.108Skamil TWAIT_FNAME); 35161.108Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 35171.108Skamil 35181.108Skamil validate_status_exited(status, exitval); 35191.108Skamil 35201.108Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 35211.108Skamil TWAIT_FNAME); 35221.108Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 35231.108Skamil} 35241.108Skamil 35251.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun) \ 35261.108SkamilATF_TC(name); \ 35271.108SkamilATF_TC_HEAD(name, tc) \ 35281.108Skamil{ \ 35291.108Skamil atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) " \ 35301.108Skamil "called from vfork(2)ed child"); \ 35311.108Skamil} \ 35321.108Skamil \ 35331.108SkamilATF_TC_BODY(name, tc) \ 35341.108Skamil{ \ 35351.108Skamil \ 35361.108Skamil traceme_vfork_fork_body(fun); \ 35371.108Skamil} 35381.108Skamil 35391.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork) 35401.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork) 35411.110Skamil#endif 35421.108Skamil 35431.108Skamil/// ---------------------------------------------------------------------------- 35441.108Skamil 35451.54Skamilenum bytes_transfer_type { 35461.54Skamil BYTES_TRANSFER_DATA, 35471.54Skamil BYTES_TRANSFER_DATAIO, 35481.54Skamil BYTES_TRANSFER_TEXT, 35491.54Skamil BYTES_TRANSFER_TEXTIO, 35501.54Skamil BYTES_TRANSFER_AUXV 35511.54Skamil}; 35521.31Skamil 35531.54Skamilstatic int __used 35541.54Skamilbytes_transfer_dummy(int a, int b, int c, int d) 35551.54Skamil{ 35561.54Skamil int e, f, g, h; 35571.1Skamil 35581.54Skamil a *= 4; 35591.54Skamil b += 3; 35601.54Skamil c -= 2; 35611.54Skamil d /= 1; 35621.1Skamil 35631.54Skamil e = strtol("10", NULL, 10); 35641.54Skamil f = strtol("20", NULL, 10); 35651.54Skamil g = strtol("30", NULL, 10); 35661.54Skamil h = strtol("40", NULL, 10); 35671.1Skamil 35681.54Skamil return (a + b * c - d) + (e * f - g / h); 35691.1Skamil} 35701.1Skamil 35711.54Skamilstatic void 35721.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type) 35731.1Skamil{ 35741.1Skamil const int exitval = 5; 35751.1Skamil const int sigval = SIGSTOP; 35761.1Skamil pid_t child, wpid; 35771.54Skamil bool skip = false; 35781.1Skamil 35791.54Skamil int lookup_me = 0; 35801.54Skamil uint8_t lookup_me8 = 0; 35811.54Skamil uint16_t lookup_me16 = 0; 35821.54Skamil uint32_t lookup_me32 = 0; 35831.54Skamil uint64_t lookup_me64 = 0; 35841.1Skamil 35851.54Skamil int magic = 0x13579246; 35861.54Skamil uint8_t magic8 = 0xab; 35871.54Skamil uint16_t magic16 = 0x1234; 35881.54Skamil uint32_t magic32 = 0x98765432; 35891.54Skamil uint64_t magic64 = 0xabcdef0123456789; 35901.1Skamil 35911.54Skamil struct ptrace_io_desc io; 35921.1Skamil#if defined(TWAIT_HAVE_STATUS) 35931.1Skamil int status; 35941.1Skamil#endif 35951.60Skre /* 513 is just enough, for the purposes of ATF it's good enough */ 35961.60Skre AuxInfo ai[513], *aip; 35971.55Schristos 35981.55Schristos ATF_REQUIRE(size < sizeof(ai)); 35991.1Skamil 36001.54Skamil /* Prepare variables for .TEXT transfers */ 36011.54Skamil switch (type) { 36021.54Skamil case BYTES_TRANSFER_TEXT: 36031.54Skamil memcpy(&magic, bytes_transfer_dummy, sizeof(magic)); 36041.54Skamil break; 36051.54Skamil case BYTES_TRANSFER_TEXTIO: 36061.54Skamil switch (size) { 36071.54Skamil case 8: 36081.54Skamil memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8)); 36091.54Skamil break; 36101.54Skamil case 16: 36111.54Skamil memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16)); 36121.54Skamil break; 36131.54Skamil case 32: 36141.54Skamil memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32)); 36151.54Skamil break; 36161.54Skamil case 64: 36171.54Skamil memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64)); 36181.54Skamil break; 36191.54Skamil } 36201.54Skamil break; 36211.54Skamil default: 36221.54Skamil break; 36231.54Skamil } 36241.1Skamil 36251.54Skamil /* Prepare variables for PIOD and AUXV transfers */ 36261.54Skamil switch (type) { 36271.54Skamil case BYTES_TRANSFER_TEXTIO: 36281.54Skamil case BYTES_TRANSFER_DATAIO: 36291.54Skamil io.piod_op = operation; 36301.54Skamil switch (size) { 36311.54Skamil case 8: 36321.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36331.54Skamil (void *)bytes_transfer_dummy : 36341.54Skamil &lookup_me8; 36351.54Skamil io.piod_addr = &lookup_me8; 36361.54Skamil io.piod_len = sizeof(lookup_me8); 36371.54Skamil break; 36381.54Skamil case 16: 36391.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36401.54Skamil (void *)bytes_transfer_dummy : 36411.54Skamil &lookup_me16; 36421.54Skamil io.piod_addr = &lookup_me16; 36431.54Skamil io.piod_len = sizeof(lookup_me16); 36441.54Skamil break; 36451.54Skamil case 32: 36461.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36471.54Skamil (void *)bytes_transfer_dummy : 36481.54Skamil &lookup_me32; 36491.54Skamil io.piod_addr = &lookup_me32; 36501.54Skamil io.piod_len = sizeof(lookup_me32); 36511.54Skamil break; 36521.54Skamil case 64: 36531.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36541.54Skamil (void *)bytes_transfer_dummy : 36551.54Skamil &lookup_me64; 36561.54Skamil io.piod_addr = &lookup_me64; 36571.54Skamil io.piod_len = sizeof(lookup_me64); 36581.54Skamil break; 36591.54Skamil default: 36601.54Skamil break; 36611.54Skamil } 36621.54Skamil break; 36631.54Skamil case BYTES_TRANSFER_AUXV: 36641.54Skamil io.piod_op = operation; 36651.54Skamil io.piod_offs = 0; 36661.54Skamil io.piod_addr = ai; 36671.54Skamil io.piod_len = size; 36681.54Skamil break; 36691.54Skamil default: 36701.54Skamil break; 36711.1Skamil } 36721.1Skamil 36731.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 36741.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 36751.1Skamil if (child == 0) { 36761.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 36771.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 36781.1Skamil 36791.54Skamil switch (type) { 36801.54Skamil case BYTES_TRANSFER_DATA: 36811.54Skamil switch (operation) { 36821.54Skamil case PT_READ_D: 36831.54Skamil case PT_READ_I: 36841.54Skamil lookup_me = magic; 36851.54Skamil break; 36861.54Skamil default: 36871.54Skamil break; 36881.54Skamil } 36891.54Skamil break; 36901.54Skamil case BYTES_TRANSFER_DATAIO: 36911.54Skamil switch (operation) { 36921.54Skamil case PIOD_READ_D: 36931.54Skamil case PIOD_READ_I: 36941.54Skamil switch (size) { 36951.54Skamil case 8: 36961.54Skamil lookup_me8 = magic8; 36971.54Skamil break; 36981.54Skamil case 16: 36991.54Skamil lookup_me16 = magic16; 37001.54Skamil break; 37011.54Skamil case 32: 37021.54Skamil lookup_me32 = magic32; 37031.54Skamil break; 37041.54Skamil case 64: 37051.54Skamil lookup_me64 = magic64; 37061.54Skamil break; 37071.54Skamil default: 37081.54Skamil break; 37091.54Skamil } 37101.54Skamil break; 37111.54Skamil default: 37121.54Skamil break; 37131.54Skamil } 37141.54Skamil default: 37151.54Skamil break; 37161.54Skamil } 37171.54Skamil 37181.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 37191.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 37201.1Skamil 37211.54Skamil /* Handle PIOD and PT separately as operation values overlap */ 37221.54Skamil switch (type) { 37231.54Skamil case BYTES_TRANSFER_DATA: 37241.54Skamil switch (operation) { 37251.54Skamil case PT_WRITE_D: 37261.54Skamil case PT_WRITE_I: 37271.54Skamil FORKEE_ASSERT_EQ(lookup_me, magic); 37281.54Skamil break; 37291.54Skamil default: 37301.54Skamil break; 37311.54Skamil } 37321.54Skamil break; 37331.54Skamil case BYTES_TRANSFER_DATAIO: 37341.54Skamil switch (operation) { 37351.54Skamil case PIOD_WRITE_D: 37361.54Skamil case PIOD_WRITE_I: 37371.54Skamil switch (size) { 37381.54Skamil case 8: 37391.54Skamil FORKEE_ASSERT_EQ(lookup_me8, magic8); 37401.54Skamil break; 37411.54Skamil case 16: 37421.54Skamil FORKEE_ASSERT_EQ(lookup_me16, magic16); 37431.54Skamil break; 37441.54Skamil case 32: 37451.54Skamil FORKEE_ASSERT_EQ(lookup_me32, magic32); 37461.54Skamil break; 37471.54Skamil case 64: 37481.54Skamil FORKEE_ASSERT_EQ(lookup_me64, magic64); 37491.54Skamil break; 37501.54Skamil default: 37511.54Skamil break; 37521.54Skamil } 37531.54Skamil break; 37541.54Skamil default: 37551.54Skamil break; 37561.54Skamil } 37571.54Skamil break; 37581.54Skamil case BYTES_TRANSFER_TEXT: 37591.54Skamil FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy, 37601.54Skamil sizeof(magic)) == 0); 37611.54Skamil break; 37621.54Skamil case BYTES_TRANSFER_TEXTIO: 37631.54Skamil switch (size) { 37641.54Skamil case 8: 37651.54Skamil FORKEE_ASSERT(memcmp(&magic8, 37661.54Skamil bytes_transfer_dummy, 37671.54Skamil sizeof(magic8)) == 0); 37681.54Skamil break; 37691.54Skamil case 16: 37701.54Skamil FORKEE_ASSERT(memcmp(&magic16, 37711.54Skamil bytes_transfer_dummy, 37721.54Skamil sizeof(magic16)) == 0); 37731.54Skamil break; 37741.54Skamil case 32: 37751.54Skamil FORKEE_ASSERT(memcmp(&magic32, 37761.54Skamil bytes_transfer_dummy, 37771.54Skamil sizeof(magic32)) == 0); 37781.54Skamil break; 37791.54Skamil case 64: 37801.54Skamil FORKEE_ASSERT(memcmp(&magic64, 37811.54Skamil bytes_transfer_dummy, 37821.54Skamil sizeof(magic64)) == 0); 37831.54Skamil break; 37841.54Skamil } 37851.54Skamil break; 37861.54Skamil default: 37871.54Skamil break; 37881.54Skamil } 37891.54Skamil 37901.13Schristos DPRINTF("Before exiting of the child process\n"); 37911.1Skamil _exit(exitval); 37921.1Skamil } 37931.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 37941.1Skamil 37951.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 37961.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 37971.1Skamil 37981.1Skamil validate_status_stopped(status, sigval); 37991.1Skamil 38001.54Skamil /* Check PaX MPROTECT */ 38011.54Skamil if (!can_we_write_to_text(child)) { 38021.54Skamil switch (type) { 38031.54Skamil case BYTES_TRANSFER_TEXTIO: 38041.54Skamil switch (operation) { 38051.54Skamil case PIOD_WRITE_D: 38061.54Skamil case PIOD_WRITE_I: 38071.54Skamil skip = true; 38081.54Skamil break; 38091.54Skamil default: 38101.54Skamil break; 38111.54Skamil } 38121.54Skamil break; 38131.54Skamil case BYTES_TRANSFER_TEXT: 38141.54Skamil switch (operation) { 38151.54Skamil case PT_WRITE_D: 38161.54Skamil case PT_WRITE_I: 38171.54Skamil skip = true; 38181.54Skamil break; 38191.54Skamil default: 38201.54Skamil break; 38211.54Skamil } 38221.54Skamil break; 38231.54Skamil default: 38241.54Skamil break; 38251.54Skamil } 38261.54Skamil } 38271.1Skamil 38281.54Skamil /* Bailout cleanly killing the child process */ 38291.54Skamil if (skip) { 38301.54Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1); 38311.54Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38321.54Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 38331.54Skamil child); 38341.1Skamil 38351.54Skamil validate_status_signaled(status, SIGKILL, 0); 38361.1Skamil 38371.54Skamil atf_tc_skip("PaX MPROTECT setup prevents writes to .text"); 38381.54Skamil } 38391.1Skamil 38401.54Skamil DPRINTF("Calling operation to transfer bytes between child=%d and " 38411.54Skamil "parent=%d\n", child, getpid()); 38421.1Skamil 38431.54Skamil switch (type) { 38441.54Skamil case BYTES_TRANSFER_TEXTIO: 38451.54Skamil case BYTES_TRANSFER_DATAIO: 38461.54Skamil case BYTES_TRANSFER_AUXV: 38471.54Skamil switch (operation) { 38481.54Skamil case PIOD_WRITE_D: 38491.54Skamil case PIOD_WRITE_I: 38501.54Skamil switch (size) { 38511.54Skamil case 8: 38521.54Skamil lookup_me8 = magic8; 38531.54Skamil break; 38541.54Skamil case 16: 38551.54Skamil lookup_me16 = magic16; 38561.54Skamil break; 38571.54Skamil case 32: 38581.54Skamil lookup_me32 = magic32; 38591.54Skamil break; 38601.54Skamil case 64: 38611.54Skamil lookup_me64 = magic64; 38621.54Skamil break; 38631.54Skamil default: 38641.54Skamil break; 38651.54Skamil } 38661.54Skamil break; 38671.54Skamil default: 38681.54Skamil break; 38691.54Skamil } 38701.54Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); 38711.54Skamil switch (operation) { 38721.54Skamil case PIOD_READ_D: 38731.54Skamil case PIOD_READ_I: 38741.54Skamil switch (size) { 38751.54Skamil case 8: 38761.54Skamil ATF_REQUIRE_EQ(lookup_me8, magic8); 38771.54Skamil break; 38781.54Skamil case 16: 38791.54Skamil ATF_REQUIRE_EQ(lookup_me16, magic16); 38801.54Skamil break; 38811.54Skamil case 32: 38821.54Skamil ATF_REQUIRE_EQ(lookup_me32, magic32); 38831.54Skamil break; 38841.54Skamil case 64: 38851.54Skamil ATF_REQUIRE_EQ(lookup_me64, magic64); 38861.54Skamil break; 38871.54Skamil default: 38881.54Skamil break; 38891.54Skamil } 38901.54Skamil break; 38911.54Skamil case PIOD_READ_AUXV: 38921.54Skamil DPRINTF("Asserting that AUXV length (%zu) is > 0\n", 38931.54Skamil io.piod_len); 38941.54Skamil ATF_REQUIRE(io.piod_len > 0); 38951.54Skamil for (aip = ai; aip->a_type != AT_NULL; aip++) 38961.54Skamil DPRINTF("a_type=%#llx a_v=%#llx\n", 38971.54Skamil (long long int)aip->a_type, 38981.54Skamil (long long int)aip->a_v); 38991.54Skamil break; 39001.54Skamil default: 39011.54Skamil break; 39021.54Skamil } 39031.54Skamil break; 39041.54Skamil case BYTES_TRANSFER_TEXT: 39051.54Skamil switch (operation) { 39061.54Skamil case PT_READ_D: 39071.54Skamil case PT_READ_I: 39081.54Skamil errno = 0; 39091.54Skamil lookup_me = ptrace(operation, child, 39101.54Skamil bytes_transfer_dummy, 0); 39111.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 39121.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 39131.54Skamil break; 39141.54Skamil case PT_WRITE_D: 39151.54Skamil case PT_WRITE_I: 39161.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, 39171.54Skamil bytes_transfer_dummy, magic) 39181.54Skamil != -1); 39191.54Skamil break; 39201.54Skamil default: 39211.54Skamil break; 39221.54Skamil } 39231.54Skamil break; 39241.54Skamil case BYTES_TRANSFER_DATA: 39251.54Skamil switch (operation) { 39261.54Skamil case PT_READ_D: 39271.54Skamil case PT_READ_I: 39281.54Skamil errno = 0; 39291.54Skamil lookup_me = ptrace(operation, child, &lookup_me, 0); 39301.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 39311.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 39321.54Skamil break; 39331.54Skamil case PT_WRITE_D: 39341.54Skamil case PT_WRITE_I: 39351.54Skamil lookup_me = magic; 39361.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me, 39371.54Skamil magic) != -1); 39381.54Skamil break; 39391.54Skamil default: 39401.54Skamil break; 39411.54Skamil } 39421.54Skamil break; 39431.54Skamil default: 39441.54Skamil break; 39451.54Skamil } 39461.1Skamil 39471.13Schristos DPRINTF("Before resuming the child process where it left off and " 39481.1Skamil "without signal to be sent\n"); 39491.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 39501.1Skamil 39511.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39521.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 39531.1Skamil 39541.1Skamil validate_status_exited(status, exitval); 39551.1Skamil 39561.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39571.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 39581.1Skamil} 39591.1Skamil 39601.61Skre#define BYTES_TRANSFER(test, operation, size, type) \ 39611.61SkreATF_TC(test); \ 39621.61SkreATF_TC_HEAD(test, tc) \ 39631.61Skre{ \ 39641.61Skre atf_tc_set_md_var(tc, "descr", \ 39651.61Skre "Verify bytes transfer operation" #operation " and size " #size \ 39661.61Skre " of type " #type); \ 39671.61Skre} \ 39681.61Skre \ 39691.61SkreATF_TC_BODY(test, tc) \ 39701.61Skre{ \ 39711.61Skre \ 39721.61Skre bytes_transfer(operation, size, BYTES_TRANSFER_##type); \ 39731.1Skamil} 39741.1Skamil 39751.54Skamil// DATA 39761.1Skamil 39771.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO) 39781.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO) 39791.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO) 39801.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO) 39811.54Skamil 39821.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO) 39831.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO) 39841.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO) 39851.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO) 39861.54Skamil 39871.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO) 39881.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO) 39891.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO) 39901.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO) 39911.54Skamil 39921.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO) 39931.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO) 39941.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO) 39951.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO) 39961.54Skamil 39971.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA) 39981.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA) 39991.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA) 40001.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA) 40011.54Skamil 40021.54Skamil// TEXT 40031.54Skamil 40041.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO) 40051.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO) 40061.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO) 40071.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO) 40081.54Skamil 40091.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO) 40101.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO) 40111.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO) 40121.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO) 40131.54Skamil 40141.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO) 40151.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO) 40161.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO) 40171.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO) 40181.54Skamil 40191.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO) 40201.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO) 40211.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO) 40221.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO) 40231.54Skamil 40241.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT) 40251.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT) 40261.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT) 40271.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT) 40281.1Skamil 40291.54Skamil// AUXV 40301.1Skamil 40311.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV) 40321.1Skamil 40331.54Skamil/// ---------------------------------------------------------------------------- 40341.1Skamil 40351.101Skamilstatic void 40361.101Skamilbytes_transfer_alignment(const char *operation) 40371.101Skamil{ 40381.101Skamil const int exitval = 5; 40391.101Skamil const int sigval = SIGSTOP; 40401.101Skamil pid_t child, wpid; 40411.101Skamil#if defined(TWAIT_HAVE_STATUS) 40421.101Skamil int status; 40431.101Skamil#endif 40441.101Skamil char *buffer; 40451.101Skamil int vector; 40461.101Skamil size_t len; 40471.101Skamil size_t i; 40481.101Skamil int op; 40491.101Skamil 40501.101Skamil struct ptrace_io_desc io; 40511.101Skamil struct ptrace_siginfo info; 40521.101Skamil 40531.101Skamil memset(&io, 0, sizeof(io)); 40541.101Skamil memset(&info, 0, sizeof(info)); 40551.101Skamil 40561.101Skamil /* Testing misaligned byte transfer crossing page boundaries */ 40571.101Skamil len = sysconf(_SC_PAGESIZE) * 2; 40581.101Skamil buffer = malloc(len); 40591.101Skamil ATF_REQUIRE(buffer != NULL); 40601.101Skamil 40611.101Skamil /* Initialize the buffer with random data */ 40621.101Skamil for (i = 0; i < len; i++) 40631.101Skamil buffer[i] = i & 0xff; 40641.101Skamil 40651.101Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 40661.101Skamil SYSCALL_REQUIRE((child = fork()) != -1); 40671.101Skamil if (child == 0) { 40681.101Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 40691.101Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 40701.101Skamil 40711.101Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 40721.101Skamil FORKEE_ASSERT(raise(sigval) == 0); 40731.101Skamil 40741.101Skamil DPRINTF("Before exiting of the child process\n"); 40751.101Skamil _exit(exitval); 40761.101Skamil } 40771.101Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 40781.101Skamil 40791.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 40801.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 40811.101Skamil 40821.101Skamil validate_status_stopped(status, sigval); 40831.101Skamil 40841.101Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 40851.101Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 40861.101Skamil != -1); 40871.101Skamil 40881.101Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 40891.101Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 40901.101Skamil "si_errno=%#x\n", 40911.101Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 40921.101Skamil info.psi_siginfo.si_errno); 40931.101Skamil 40941.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 40951.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 40961.101Skamil 40971.101Skamil if (strcmp(operation, "PT_READ_I") == 0 || 40981.101Skamil strcmp(operation, "PT_READ_D") == 0) { 40991.101Skamil if (strcmp(operation, "PT_READ_I")) 41001.101Skamil op = PT_READ_I; 41011.101Skamil else 41021.101Skamil op = PT_READ_D; 41031.101Skamil 41041.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41051.101Skamil errno = 0; 41061.101Skamil vector = ptrace(op, child, buffer + i, 0); 41071.101Skamil ATF_REQUIRE_EQ(errno, 0); 41081.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 41091.101Skamil } 41101.101Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 41111.101Skamil strcmp(operation, "PT_WRITE_D") == 0) { 41121.101Skamil if (strcmp(operation, "PT_WRITE_I")) 41131.101Skamil op = PT_WRITE_I; 41141.101Skamil else 41151.101Skamil op = PT_WRITE_D; 41161.101Skamil 41171.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41181.101Skamil memcpy(&vector, buffer + i, sizeof(int)); 41191.101Skamil SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector) 41201.101Skamil != -1); 41211.101Skamil } 41221.101Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 41231.101Skamil strcmp(operation, "PIOD_READ_D") == 0) { 41241.101Skamil if (strcmp(operation, "PIOD_READ_I")) 41251.101Skamil op = PIOD_READ_I; 41261.101Skamil else 41271.101Skamil op = PIOD_READ_D; 41281.101Skamil 41291.101Skamil io.piod_op = op; 41301.101Skamil io.piod_addr = &vector; 41311.101Skamil io.piod_len = sizeof(int); 41321.101Skamil 41331.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41341.101Skamil io.piod_offs = buffer + i; 41351.101Skamil 41361.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41371.101Skamil != -1); 41381.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 41391.101Skamil } 41401.101Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 41411.101Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 41421.101Skamil if (strcmp(operation, "PIOD_WRITE_I")) 41431.101Skamil op = PIOD_WRITE_I; 41441.101Skamil else 41451.101Skamil op = PIOD_WRITE_D; 41461.101Skamil 41471.101Skamil io.piod_op = op; 41481.101Skamil io.piod_addr = &vector; 41491.101Skamil io.piod_len = sizeof(int); 41501.101Skamil 41511.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41521.101Skamil io.piod_offs = buffer + i; 41531.101Skamil 41541.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41551.101Skamil != -1); 41561.101Skamil } 41571.101Skamil } else if (strcmp(operation, "PIOD_READ_AUXV") == 0) { 41581.101Skamil io.piod_op = PIOD_READ_AUXV; 41591.101Skamil io.piod_addr = &vector; 41601.101Skamil io.piod_len = sizeof(int); 41611.101Skamil 41621.101Skamil errno = 0; 41631.101Skamil i = 0; 41641.101Skamil /* Read the whole AUXV vector, it has no clear length */ 41651.120Skamil while (io.piod_len > 0) { 41661.101Skamil io.piod_offs = (void *)(intptr_t)i; 41671.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41681.120Skamil != -1 || (io.piod_len == 0 && i > 0)); 41691.101Skamil ++i; 41701.101Skamil } 41711.101Skamil } 41721.101Skamil 41731.101Skamil DPRINTF("Before resuming the child process where it left off " 41741.101Skamil "and without signal to be sent\n"); 41751.101Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 41761.101Skamil 41771.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41781.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 41791.101Skamil child); 41801.101Skamil 41811.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41821.101Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 41831.101Skamil} 41841.101Skamil 41851.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation) \ 41861.101SkamilATF_TC(test); \ 41871.101SkamilATF_TC_HEAD(test, tc) \ 41881.101Skamil{ \ 41891.101Skamil atf_tc_set_md_var(tc, "descr", \ 41901.101Skamil "Verify bytes transfer for potentially misaligned " \ 41911.101Skamil "operation " operation); \ 41921.101Skamil} \ 41931.101Skamil \ 41941.101SkamilATF_TC_BODY(test, tc) \ 41951.101Skamil{ \ 41961.101Skamil \ 41971.101Skamil bytes_transfer_alignment(operation); \ 41981.101Skamil} 41991.101Skamil 42001.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I") 42011.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D") 42021.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I") 42031.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D") 42041.101Skamil 42051.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I") 42061.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D") 42071.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I") 42081.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D") 42091.101Skamil 42101.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV") 42111.101Skamil 42121.101Skamil/// ---------------------------------------------------------------------------- 42131.101Skamil 42141.115Skamilstatic void 42151.115Skamilbytes_transfer_eof(const char *operation) 42161.115Skamil{ 42171.115Skamil const int exitval = 5; 42181.115Skamil const int sigval = SIGSTOP; 42191.115Skamil pid_t child, wpid; 42201.115Skamil#if defined(TWAIT_HAVE_STATUS) 42211.115Skamil int status; 42221.115Skamil#endif 42231.115Skamil FILE *fp; 42241.115Skamil char *p; 42251.115Skamil int vector; 42261.115Skamil int op; 42271.115Skamil 42281.115Skamil struct ptrace_io_desc io; 42291.115Skamil struct ptrace_siginfo info; 42301.115Skamil 42311.115Skamil memset(&io, 0, sizeof(io)); 42321.115Skamil memset(&info, 0, sizeof(info)); 42331.115Skamil 42341.115Skamil vector = 0; 42351.115Skamil 42361.115Skamil fp = tmpfile(); 42371.115Skamil ATF_REQUIRE(fp != NULL); 42381.115Skamil 42391.115Skamil p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0); 42401.115Skamil ATF_REQUIRE(p != MAP_FAILED); 42411.115Skamil 42421.115Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 42431.115Skamil SYSCALL_REQUIRE((child = fork()) != -1); 42441.115Skamil if (child == 0) { 42451.115Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 42461.115Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 42471.115Skamil 42481.115Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 42491.115Skamil FORKEE_ASSERT(raise(sigval) == 0); 42501.115Skamil 42511.115Skamil DPRINTF("Before exiting of the child process\n"); 42521.115Skamil _exit(exitval); 42531.115Skamil } 42541.115Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 42551.115Skamil 42561.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 42571.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 42581.115Skamil 42591.115Skamil validate_status_stopped(status, sigval); 42601.115Skamil 42611.115Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 42621.115Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 42631.115Skamil != -1); 42641.115Skamil 42651.115Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 42661.115Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 42671.115Skamil "si_errno=%#x\n", 42681.115Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 42691.115Skamil info.psi_siginfo.si_errno); 42701.115Skamil 42711.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 42721.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 42731.115Skamil 42741.115Skamil if (strcmp(operation, "PT_READ_I") == 0 || 42751.115Skamil strcmp(operation, "PT_READ_D") == 0) { 42761.115Skamil if (strcmp(operation, "PT_READ_I")) 42771.115Skamil op = PT_READ_I; 42781.115Skamil else 42791.115Skamil op = PT_READ_D; 42801.115Skamil 42811.115Skamil errno = 0; 42821.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, 0) == -1); 42831.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 42841.115Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 42851.115Skamil strcmp(operation, "PT_WRITE_D") == 0) { 42861.115Skamil if (strcmp(operation, "PT_WRITE_I")) 42871.115Skamil op = PT_WRITE_I; 42881.115Skamil else 42891.115Skamil op = PT_WRITE_D; 42901.115Skamil 42911.115Skamil errno = 0; 42921.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, vector) == -1); 42931.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 42941.115Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 42951.115Skamil strcmp(operation, "PIOD_READ_D") == 0) { 42961.115Skamil if (strcmp(operation, "PIOD_READ_I")) 42971.115Skamil op = PIOD_READ_I; 42981.115Skamil else 42991.115Skamil op = PIOD_READ_D; 43001.115Skamil 43011.115Skamil io.piod_op = op; 43021.115Skamil io.piod_addr = &vector; 43031.115Skamil io.piod_len = sizeof(int); 43041.115Skamil io.piod_offs = p; 43051.115Skamil 43061.115Skamil errno = 0; 43071.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 43081.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43091.115Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 43101.115Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 43111.115Skamil if (strcmp(operation, "PIOD_WRITE_I")) 43121.115Skamil op = PIOD_WRITE_I; 43131.115Skamil else 43141.115Skamil op = PIOD_WRITE_D; 43151.115Skamil 43161.115Skamil io.piod_op = op; 43171.115Skamil io.piod_addr = &vector; 43181.115Skamil io.piod_len = sizeof(int); 43191.115Skamil io.piod_offs = p; 43201.115Skamil 43211.115Skamil errno = 0; 43221.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 43231.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43241.115Skamil } 43251.115Skamil 43261.115Skamil DPRINTF("Before resuming the child process where it left off " 43271.115Skamil "and without signal to be sent\n"); 43281.115Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 43291.115Skamil 43301.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43311.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 43321.115Skamil child); 43331.115Skamil 43341.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43351.115Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 43361.115Skamil} 43371.115Skamil 43381.115Skamil#define BYTES_TRANSFER_EOF(test, operation) \ 43391.115SkamilATF_TC(test); \ 43401.115SkamilATF_TC_HEAD(test, tc) \ 43411.115Skamil{ \ 43421.115Skamil atf_tc_set_md_var(tc, "descr", \ 43431.115Skamil "Verify bytes EOF byte transfer for the " operation \ 43441.115Skamil " operation"); \ 43451.115Skamil} \ 43461.115Skamil \ 43471.115SkamilATF_TC_BODY(test, tc) \ 43481.115Skamil{ \ 43491.115Skamil \ 43501.115Skamil bytes_transfer_eof(operation); \ 43511.115Skamil} 43521.115Skamil 43531.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_i, "PT_READ_I") 43541.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_d, "PT_READ_D") 43551.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_i, "PT_WRITE_I") 43561.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_d, "PT_WRITE_D") 43571.115Skamil 43581.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_i, "PIOD_READ_I") 43591.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_d, "PIOD_READ_D") 43601.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_i, "PIOD_WRITE_I") 43611.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_d, "PIOD_WRITE_D") 43621.115Skamil 43631.115Skamil/// ---------------------------------------------------------------------------- 43641.115Skamil 43651.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS) 43661.72Skamilstatic void 43671.72Skamilaccess_regs(const char *regset, const char *aux) 43681.1Skamil{ 43691.1Skamil const int exitval = 5; 43701.1Skamil const int sigval = SIGSTOP; 43711.1Skamil pid_t child, wpid; 43721.1Skamil#if defined(TWAIT_HAVE_STATUS) 43731.1Skamil int status; 43741.1Skamil#endif 43751.72Skamil#if defined(HAVE_GPREGS) 43761.72Skamil struct reg gpr; 43771.76Sscole register_t rgstr; 43781.1Skamil#endif 43791.72Skamil#if defined(HAVE_FPREGS) 43801.72Skamil struct fpreg fpr; 43811.1Skamil#endif 43821.76Sscole 43831.72Skamil#if !defined(HAVE_GPREGS) 43841.72Skamil if (strcmp(regset, "regs") == 0) 43851.72Skamil atf_tc_fail("Impossible test scenario!"); 43861.1Skamil#endif 43871.1Skamil 43881.72Skamil#if !defined(HAVE_FPREGS) 43891.72Skamil if (strcmp(regset, "fpregs") == 0) 43901.72Skamil atf_tc_fail("Impossible test scenario!"); 43911.1Skamil#endif 43921.1Skamil 43931.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 43941.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 43951.1Skamil if (child == 0) { 43961.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 43971.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 43981.1Skamil 43991.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 44001.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 44011.1Skamil 44021.13Schristos DPRINTF("Before exiting of the child process\n"); 44031.1Skamil _exit(exitval); 44041.1Skamil } 44051.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 44061.1Skamil 44071.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44081.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44091.1Skamil 44101.1Skamil validate_status_stopped(status, sigval); 44111.1Skamil 44121.1Skamil#if defined(HAVE_GPREGS) 44131.72Skamil if (strcmp(regset, "regs") == 0) { 44141.72Skamil DPRINTF("Call GETREGS for the child process\n"); 44151.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1); 44161.72Skamil 44171.72Skamil if (strcmp(aux, "none") == 0) { 44181.72Skamil DPRINTF("Retrieved registers\n"); 44191.72Skamil } else if (strcmp(aux, "pc") == 0) { 44201.72Skamil rgstr = PTRACE_REG_PC(&gpr); 44211.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44221.72Skamil } else if (strcmp(aux, "set_pc") == 0) { 44231.72Skamil rgstr = PTRACE_REG_PC(&gpr); 44241.72Skamil PTRACE_REG_SET_PC(&gpr, rgstr); 44251.72Skamil } else if (strcmp(aux, "sp") == 0) { 44261.72Skamil rgstr = PTRACE_REG_SP(&gpr); 44271.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44281.72Skamil } else if (strcmp(aux, "intrv") == 0) { 44291.72Skamil rgstr = PTRACE_REG_INTRV(&gpr); 44301.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44311.72Skamil } else if (strcmp(aux, "setregs") == 0) { 44321.72Skamil DPRINTF("Call SETREGS for the child process\n"); 44331.72Skamil SYSCALL_REQUIRE( 44341.72Skamil ptrace(PT_GETREGS, child, &gpr, 0) != -1); 44351.72Skamil } 44361.72Skamil } 44371.1Skamil#endif 44381.1Skamil 44391.72Skamil#if defined(HAVE_FPREGS) 44401.72Skamil if (strcmp(regset, "fpregs") == 0) { 44411.72Skamil DPRINTF("Call GETFPREGS for the child process\n"); 44421.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1); 44431.72Skamil 44441.72Skamil if (strcmp(aux, "getfpregs") == 0) { 44451.72Skamil DPRINTF("Retrieved FP registers\n"); 44461.72Skamil } else if (strcmp(aux, "setfpregs") == 0) { 44471.72Skamil DPRINTF("Call SETFPREGS for the child\n"); 44481.72Skamil SYSCALL_REQUIRE( 44491.72Skamil ptrace(PT_SETFPREGS, child, &fpr, 0) != -1); 44501.72Skamil } 44511.1Skamil } 44521.1Skamil#endif 44531.1Skamil 44541.13Schristos DPRINTF("Before resuming the child process where it left off and " 44551.1Skamil "without signal to be sent\n"); 44561.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 44571.1Skamil 44581.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44591.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44601.1Skamil 44611.1Skamil validate_status_exited(status, exitval); 44621.1Skamil 44631.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44641.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 44651.1Skamil} 44661.1Skamil 44671.72Skamil#define ACCESS_REGS(test, regset, aux) \ 44681.72SkamilATF_TC(test); \ 44691.72SkamilATF_TC_HEAD(test, tc) \ 44701.72Skamil{ \ 44711.72Skamil atf_tc_set_md_var(tc, "descr", \ 44721.72Skamil "Verify " regset " with auxiliary operation: " aux); \ 44731.72Skamil} \ 44741.72Skamil \ 44751.72SkamilATF_TC_BODY(test, tc) \ 44761.72Skamil{ \ 44771.72Skamil \ 44781.72Skamil access_regs(regset, aux); \ 44791.1Skamil} 44801.1Skamil#endif 44811.1Skamil 44821.72Skamil#if defined(HAVE_GPREGS) 44831.72SkamilACCESS_REGS(access_regs1, "regs", "none") 44841.72SkamilACCESS_REGS(access_regs2, "regs", "pc") 44851.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc") 44861.72SkamilACCESS_REGS(access_regs4, "regs", "sp") 44871.72SkamilACCESS_REGS(access_regs5, "regs", "intrv") 44881.72SkamilACCESS_REGS(access_regs6, "regs", "setregs") 44891.1Skamil#endif 44901.1Skamil#if defined(HAVE_FPREGS) 44911.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs") 44921.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs") 44931.1Skamil#endif 44941.1Skamil 44951.72Skamil/// ---------------------------------------------------------------------------- 44961.1Skamil 44971.1Skamil#if defined(PT_STEP) 44981.1Skamilstatic void 44991.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored) 45001.1Skamil{ 45011.1Skamil const int exitval = 5; 45021.1Skamil const int sigval = SIGSTOP; 45031.1Skamil pid_t child, wpid; 45041.1Skamil#if defined(TWAIT_HAVE_STATUS) 45051.1Skamil int status; 45061.1Skamil#endif 45071.1Skamil int happy; 45081.95Skamil struct sigaction sa; 45091.81Skamil struct ptrace_siginfo info; 45101.95Skamil sigset_t intmask; 45111.95Skamil struct kinfo_proc2 kp; 45121.95Skamil size_t len = sizeof(kp); 45131.95Skamil 45141.95Skamil int name[6]; 45151.95Skamil const size_t namelen = __arraycount(name); 45161.95Skamil ki_sigset_t kp_sigmask; 45171.95Skamil ki_sigset_t kp_sigignore; 45181.1Skamil 45191.1Skamil#if defined(__arm__) 45201.1Skamil /* PT_STEP not supported on arm 32-bit */ 45211.1Skamil atf_tc_expect_fail("PR kern/52119"); 45221.1Skamil#endif 45231.1Skamil 45241.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 45251.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 45261.1Skamil if (child == 0) { 45271.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 45281.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 45291.1Skamil 45301.95Skamil if (masked) { 45311.95Skamil sigemptyset(&intmask); 45321.95Skamil sigaddset(&intmask, SIGTRAP); 45331.95Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 45341.95Skamil } 45351.95Skamil 45361.95Skamil if (ignored) { 45371.95Skamil memset(&sa, 0, sizeof(sa)); 45381.95Skamil sa.sa_handler = SIG_IGN; 45391.95Skamil sigemptyset(&sa.sa_mask); 45401.95Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 45411.95Skamil } 45421.95Skamil 45431.1Skamil happy = check_happy(999); 45441.1Skamil 45451.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 45461.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 45471.1Skamil 45481.1Skamil FORKEE_ASSERT_EQ(happy, check_happy(999)); 45491.1Skamil 45501.13Schristos DPRINTF("Before exiting of the child process\n"); 45511.1Skamil _exit(exitval); 45521.1Skamil } 45531.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 45541.1Skamil 45551.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45561.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 45571.1Skamil 45581.1Skamil validate_status_stopped(status, sigval); 45591.1Skamil 45601.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 45611.81Skamil SYSCALL_REQUIRE( 45621.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 45631.81Skamil 45641.81Skamil DPRINTF("Before checking siginfo_t\n"); 45651.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 45661.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 45671.81Skamil 45681.95Skamil name[0] = CTL_KERN, 45691.95Skamil name[1] = KERN_PROC2, 45701.95Skamil name[2] = KERN_PROC_PID; 45711.95Skamil name[3] = child; 45721.95Skamil name[4] = sizeof(kp); 45731.95Skamil name[5] = 1; 45741.95Skamil 45751.95Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 45761.95Skamil 45771.95Skamil if (masked) 45781.95Skamil kp_sigmask = kp.p_sigmask; 45791.95Skamil 45801.95Skamil if (ignored) 45811.95Skamil kp_sigignore = kp.p_sigignore; 45821.95Skamil 45831.1Skamil while (N --> 0) { 45841.2Skamil if (setstep) { 45851.13Schristos DPRINTF("Before resuming the child process where it " 45861.2Skamil "left off and without signal to be sent (use " 45871.9Skamil "PT_SETSTEP and PT_CONTINUE)\n"); 45881.13Schristos SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1); 45891.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) 45901.2Skamil != -1); 45911.2Skamil } else { 45921.13Schristos DPRINTF("Before resuming the child process where it " 45931.2Skamil "left off and without signal to be sent (use " 45941.2Skamil "PT_STEP)\n"); 45951.13Schristos SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) 45961.2Skamil != -1); 45971.2Skamil } 45981.1Skamil 45991.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46001.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 46011.1Skamil child); 46021.1Skamil 46031.1Skamil validate_status_stopped(status, SIGTRAP); 46041.2Skamil 46051.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 46061.81Skamil SYSCALL_REQUIRE( 46071.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 46081.81Skamil 46091.81Skamil DPRINTF("Before checking siginfo_t\n"); 46101.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 46111.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE); 46121.81Skamil 46131.2Skamil if (setstep) { 46141.13Schristos SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1); 46151.2Skamil } 46161.95Skamil 46171.95Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 46181.95Skamil 46191.95Skamil if (masked) { 46201.95Skamil DPRINTF("kp_sigmask=" 46211.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46221.95Skamil PRIx32 "\n", 46231.95Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 46241.95Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 46251.95Skamil 46261.95Skamil DPRINTF("kp.p_sigmask=" 46271.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46281.95Skamil PRIx32 "\n", 46291.95Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 46301.95Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 46311.95Skamil 46321.95Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 46331.95Skamil sizeof(kp_sigmask))); 46341.95Skamil } 46351.95Skamil 46361.95Skamil if (ignored) { 46371.95Skamil DPRINTF("kp_sigignore=" 46381.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46391.95Skamil PRIx32 "\n", 46401.95Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 46411.95Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 46421.95Skamil 46431.95Skamil DPRINTF("kp.p_sigignore=" 46441.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46451.95Skamil PRIx32 "\n", 46461.95Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 46471.95Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 46481.95Skamil 46491.95Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 46501.95Skamil sizeof(kp_sigignore))); 46511.95Skamil } 46521.1Skamil } 46531.1Skamil 46541.13Schristos DPRINTF("Before resuming the child process where it left off and " 46551.1Skamil "without signal to be sent\n"); 46561.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 46571.1Skamil 46581.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46591.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 46601.1Skamil 46611.1Skamil validate_status_exited(status, exitval); 46621.1Skamil 46631.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46641.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 46651.1Skamil} 46661.1Skamil 46671.73Skamil#define PTRACE_STEP(test, N, setstep) \ 46681.73SkamilATF_TC(test); \ 46691.73SkamilATF_TC_HEAD(test, tc) \ 46701.73Skamil{ \ 46711.73Skamil atf_tc_set_md_var(tc, "descr", \ 46721.74Skamil "Verify " #N " (PT_SETSTEP set to: " #setstep ")"); \ 46731.73Skamil} \ 46741.73Skamil \ 46751.73SkamilATF_TC_BODY(test, tc) \ 46761.73Skamil{ \ 46771.73Skamil \ 46781.95Skamil ptrace_step(N, setstep, false, false); \ 46791.1Skamil} 46801.1Skamil 46811.73SkamilPTRACE_STEP(step1, 1, 0) 46821.73SkamilPTRACE_STEP(step2, 2, 0) 46831.73SkamilPTRACE_STEP(step3, 3, 0) 46841.73SkamilPTRACE_STEP(step4, 4, 0) 46851.73SkamilPTRACE_STEP(setstep1, 1, 1) 46861.73SkamilPTRACE_STEP(setstep2, 2, 1) 46871.73SkamilPTRACE_STEP(setstep3, 3, 1) 46881.73SkamilPTRACE_STEP(setstep4, 4, 1) 46891.95Skamil 46901.95SkamilATF_TC(step_signalmasked); 46911.95SkamilATF_TC_HEAD(step_signalmasked, tc) 46921.95Skamil{ 46931.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP"); 46941.95Skamil} 46951.95Skamil 46961.95SkamilATF_TC_BODY(step_signalmasked, tc) 46971.95Skamil{ 46981.95Skamil 46991.95Skamil ptrace_step(1, 0, true, false); 47001.95Skamil} 47011.95Skamil 47021.95SkamilATF_TC(step_signalignored); 47031.95SkamilATF_TC_HEAD(step_signalignored, tc) 47041.95Skamil{ 47051.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP"); 47061.95Skamil} 47071.95Skamil 47081.95SkamilATF_TC_BODY(step_signalignored, tc) 47091.95Skamil{ 47101.95Skamil 47111.95Skamil ptrace_step(1, 0, false, true); 47121.95Skamil} 47131.1Skamil#endif 47141.1Skamil 47151.73Skamil/// ---------------------------------------------------------------------------- 47161.1Skamil 47171.75Skamilstatic void 47181.75Skamilptrace_kill(const char *type) 47191.1Skamil{ 47201.75Skamil const int sigval = SIGSTOP; 47211.1Skamil pid_t child, wpid; 47221.1Skamil#if defined(TWAIT_HAVE_STATUS) 47231.1Skamil int status; 47241.1Skamil#endif 47251.1Skamil 47261.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 47271.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 47281.1Skamil if (child == 0) { 47291.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 47301.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 47311.1Skamil 47321.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 47331.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 47341.1Skamil 47351.1Skamil /* NOTREACHED */ 47361.1Skamil FORKEE_ASSERTX(0 && 47371.1Skamil "Child should be terminated by a signal from its parent"); 47381.1Skamil } 47391.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 47401.1Skamil 47411.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47421.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47431.1Skamil 47441.1Skamil validate_status_stopped(status, sigval); 47451.1Skamil 47461.75Skamil DPRINTF("Before killing the child process with %s\n", type); 47471.75Skamil if (strcmp(type, "ptrace(PT_KILL)") == 0) { 47481.75Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1); 47491.75Skamil } else if (strcmp(type, "kill(SIGKILL)") == 0) { 47501.75Skamil kill(child, SIGKILL); 47511.75Skamil } else if (strcmp(type, "killpg(SIGKILL)") == 0) { 47521.75Skamil setpgid(child, 0); 47531.75Skamil killpg(getpgid(child), SIGKILL); 47541.75Skamil } 47551.1Skamil 47561.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47571.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47581.1Skamil 47591.75Skamil validate_status_signaled(status, SIGKILL, 0); 47601.1Skamil 47611.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47621.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 47631.1Skamil} 47641.1Skamil 47651.75Skamil#define PTRACE_KILL(test, type) \ 47661.75SkamilATF_TC(test); \ 47671.75SkamilATF_TC_HEAD(test, tc) \ 47681.75Skamil{ \ 47691.75Skamil atf_tc_set_md_var(tc, "descr", \ 47701.75Skamil "Verify killing the child with " type); \ 47711.75Skamil} \ 47721.75Skamil \ 47731.75SkamilATF_TC_BODY(test, tc) \ 47741.75Skamil{ \ 47751.75Skamil \ 47761.75Skamil ptrace_kill(type); \ 47771.1Skamil} 47781.1Skamil 47791.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1 47801.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)") 47811.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)") 47821.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)") 47831.1Skamil 47841.75Skamil/// ---------------------------------------------------------------------------- 47851.1Skamil 47861.77Skamilstatic void 47871.77Skamiltraceme_lwpinfo(const int threads) 47881.1Skamil{ 47891.1Skamil const int sigval = SIGSTOP; 47901.77Skamil const int sigval2 = SIGINT; 47911.1Skamil pid_t child, wpid; 47921.1Skamil#if defined(TWAIT_HAVE_STATUS) 47931.1Skamil int status; 47941.1Skamil#endif 47951.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 47961.77Skamil struct ptrace_siginfo info; 47971.77Skamil 47981.77Skamil /* Maximum number of supported threads in this test */ 47991.77Skamil pthread_t t[3]; 48001.77Skamil int n, rv; 48011.77Skamil 48021.77Skamil ATF_REQUIRE((int)__arraycount(t) >= threads); 48031.1Skamil 48041.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 48051.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 48061.1Skamil if (child == 0) { 48071.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 48081.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 48091.1Skamil 48101.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 48111.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 48121.1Skamil 48131.77Skamil for (n = 0; n < threads; n++) { 48141.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 48151.77Skamil FORKEE_ASSERT(rv == 0); 48161.77Skamil } 48171.77Skamil 48181.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval2)); 48191.77Skamil FORKEE_ASSERT(raise(sigval2) == 0); 48201.77Skamil 48211.77Skamil /* NOTREACHED */ 48221.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 48231.1Skamil } 48241.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 48251.1Skamil 48261.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48271.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48281.1Skamil 48291.1Skamil validate_status_stopped(status, sigval); 48301.1Skamil 48311.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 48321.77Skamil SYSCALL_REQUIRE( 48331.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 48341.77Skamil 48351.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 48361.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 48371.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 48381.77Skamil info.psi_siginfo.si_errno); 48391.77Skamil 48401.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 48411.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 48421.77Skamil 48431.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48441.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48451.1Skamil 48461.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 48471.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 48481.1Skamil 48491.13Schristos DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n", 48501.77Skamil lwp.pl_lwpid); 48511.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 48521.1Skamil 48531.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48541.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48551.1Skamil 48561.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 48571.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 48581.1Skamil 48591.13Schristos DPRINTF("Before resuming the child process where it left off and " 48601.1Skamil "without signal to be sent\n"); 48611.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 48621.1Skamil 48631.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48641.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48651.1Skamil 48661.77Skamil validate_status_stopped(status, sigval2); 48671.77Skamil 48681.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 48691.77Skamil SYSCALL_REQUIRE( 48701.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 48711.77Skamil 48721.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 48731.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 48741.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 48751.77Skamil info.psi_siginfo.si_errno); 48761.77Skamil 48771.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2); 48781.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 48791.77Skamil 48801.77Skamil memset(&lwp, 0, sizeof(lwp)); 48811.77Skamil 48821.77Skamil for (n = 0; n <= threads; n++) { 48831.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48841.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48851.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 48861.77Skamil 48871.77Skamil DPRINTF("Assert that the thread exists\n"); 48881.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 48891.77Skamil 48901.77Skamil DPRINTF("Assert that lwp thread %d received expected event\n", 48911.77Skamil lwp.pl_lwpid); 48921.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ? 48931.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 48941.77Skamil } 48951.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48961.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48971.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 48981.77Skamil 48991.77Skamil DPRINTF("Assert that there are no more threads\n"); 49001.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 49011.77Skamil 49021.77Skamil DPRINTF("Before resuming the child process where it left off and " 49031.77Skamil "without signal to be sent\n"); 49041.77Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1); 49051.77Skamil 49061.77Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49071.77Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 49081.77Skamil 49091.77Skamil validate_status_signaled(status, SIGKILL, 0); 49101.1Skamil 49111.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49121.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 49131.1Skamil} 49141.1Skamil 49151.77Skamil#define TRACEME_LWPINFO(test, threads) \ 49161.77SkamilATF_TC(test); \ 49171.77SkamilATF_TC_HEAD(test, tc) \ 49181.77Skamil{ \ 49191.77Skamil atf_tc_set_md_var(tc, "descr", \ 49201.77Skamil "Verify LWPINFO with the child with " #threads \ 49211.77Skamil " spawned extra threads"); \ 49221.77Skamil} \ 49231.77Skamil \ 49241.77SkamilATF_TC_BODY(test, tc) \ 49251.77Skamil{ \ 49261.77Skamil \ 49271.77Skamil traceme_lwpinfo(threads); \ 49281.1Skamil} 49291.1Skamil 49301.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0) 49311.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1) 49321.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2) 49331.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3) 49341.77Skamil 49351.77Skamil/// ---------------------------------------------------------------------------- 49361.77Skamil 49371.77Skamil#if defined(TWAIT_HAVE_PID) 49381.77Skamilstatic void 49391.77Skamilattach_lwpinfo(const int threads) 49401.1Skamil{ 49411.77Skamil const int sigval = SIGINT; 49421.1Skamil struct msg_fds parent_tracee, parent_tracer; 49431.1Skamil const int exitval_tracer = 10; 49441.1Skamil pid_t tracee, tracer, wpid; 49451.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 49461.1Skamil#if defined(TWAIT_HAVE_STATUS) 49471.1Skamil int status; 49481.1Skamil#endif 49491.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 49501.77Skamil struct ptrace_siginfo info; 49511.77Skamil 49521.77Skamil /* Maximum number of supported threads in this test */ 49531.77Skamil pthread_t t[3]; 49541.77Skamil int n, rv; 49551.1Skamil 49561.13Schristos DPRINTF("Spawn tracee\n"); 49571.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 49581.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 49591.1Skamil tracee = atf_utils_fork(); 49601.1Skamil if (tracee == 0) { 49611.1Skamil /* Wait for message from the parent */ 49621.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 49631.1Skamil 49641.77Skamil CHILD_FROM_PARENT("spawn threads", parent_tracee, msg); 49651.77Skamil 49661.77Skamil for (n = 0; n < threads; n++) { 49671.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 49681.77Skamil FORKEE_ASSERT(rv == 0); 49691.77Skamil } 49701.77Skamil 49711.77Skamil CHILD_TO_PARENT("tracee exit", parent_tracee, msg); 49721.77Skamil 49731.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 49741.77Skamil FORKEE_ASSERT(raise(sigval) == 0); 49751.77Skamil 49761.77Skamil /* NOTREACHED */ 49771.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 49781.1Skamil } 49791.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 49801.1Skamil 49811.13Schristos DPRINTF("Spawn debugger\n"); 49821.1Skamil tracer = atf_utils_fork(); 49831.1Skamil if (tracer == 0) { 49841.1Skamil /* No IPC to communicate with the child */ 49851.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 49861.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 49871.1Skamil 49881.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 49891.1Skamil FORKEE_REQUIRE_SUCCESS( 49901.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 49911.1Skamil 49921.1Skamil forkee_status_stopped(status, SIGSTOP); 49931.1Skamil 49941.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 49951.77Skamil "tracee"); 49961.77Skamil FORKEE_ASSERT( 49971.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 49981.77Skamil 49991.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 50001.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 50011.77Skamil "si_errno=%#x\n", 50021.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 50031.77Skamil info.psi_siginfo.si_errno); 50041.77Skamil 50051.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 50061.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 50071.77Skamil 50081.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 50091.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 50101.1Skamil != -1); 50111.1Skamil 50121.13Schristos DPRINTF("Assert that there exists a thread\n"); 50131.77Skamil FORKEE_ASSERTX(lwp.pl_lwpid > 0); 50141.1Skamil 50151.13Schristos DPRINTF("Assert that lwp thread %d received event " 50161.77Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 50171.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 50181.1Skamil 50191.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50201.77Skamil "tracee\n"); 50211.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 50221.1Skamil != -1); 50231.1Skamil 50241.77Skamil DPRINTF("Assert that there are no more lwp threads in " 50251.77Skamil "tracee\n"); 50261.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 50271.1Skamil 50281.1Skamil /* Resume tracee with PT_CONTINUE */ 50291.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 50301.1Skamil 50311.1Skamil /* Inform parent that tracer has attached to tracee */ 50321.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 50331.77Skamil 50341.1Skamil /* Wait for parent */ 50351.1Skamil CHILD_FROM_PARENT("tracer wait", parent_tracer, msg); 50361.1Skamil 50371.77Skamil /* Wait for tracee and assert that it raised a signal */ 50381.77Skamil FORKEE_REQUIRE_SUCCESS( 50391.77Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 50401.77Skamil 50411.77Skamil forkee_status_stopped(status, SIGINT); 50421.77Skamil 50431.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 50441.77Skamil "child"); 50451.77Skamil FORKEE_ASSERT( 50461.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 50471.77Skamil 50481.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 50491.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 50501.77Skamil "si_errno=%#x\n", 50511.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 50521.77Skamil info.psi_siginfo.si_errno); 50531.77Skamil 50541.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 50551.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 50561.77Skamil 50571.77Skamil memset(&lwp, 0, sizeof(lwp)); 50581.77Skamil 50591.77Skamil for (n = 0; n <= threads; n++) { 50601.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50611.77Skamil "child\n"); 50621.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, 50631.77Skamil sizeof(lwp)) != -1); 50641.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 50651.77Skamil 50661.77Skamil DPRINTF("Assert that the thread exists\n"); 50671.77Skamil FORKEE_ASSERT(lwp.pl_lwpid > 0); 50681.77Skamil 50691.77Skamil DPRINTF("Assert that lwp thread %d received expected " 50701.77Skamil "event\n", lwp.pl_lwpid); 50711.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 50721.77Skamil info.psi_lwpid == lwp.pl_lwpid ? 50731.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 50741.77Skamil } 50751.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50761.77Skamil "tracee\n"); 50771.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 50781.77Skamil != -1); 50791.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 50801.77Skamil 50811.77Skamil DPRINTF("Assert that there are no more threads\n"); 50821.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 50831.77Skamil 50841.77Skamil DPRINTF("Before resuming the child process where it left off " 50851.77Skamil "and without signal to be sent\n"); 50861.77Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL) 50871.77Skamil != -1); 50881.77Skamil 50891.1Skamil /* Wait for tracee and assert that it exited */ 50901.1Skamil FORKEE_REQUIRE_SUCCESS( 50911.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 50921.1Skamil 50931.77Skamil forkee_status_signaled(status, SIGKILL, 0); 50941.1Skamil 50951.13Schristos DPRINTF("Before exiting of the tracer process\n"); 50961.1Skamil _exit(exitval_tracer); 50971.1Skamil } 50981.1Skamil 50991.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 51001.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 51011.1Skamil 51021.77Skamil DPRINTF("Resume the tracee and spawn threads\n"); 51031.77Skamil PARENT_TO_CHILD("spawn threads", parent_tracee, msg); 51041.77Skamil 51051.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 51061.77Skamil PARENT_FROM_CHILD("tracee exit", parent_tracee, msg); 51071.1Skamil 51081.77Skamil DPRINTF("Resume the tracer and let it detect multiple threads\n"); 51091.1Skamil PARENT_TO_CHILD("tracer wait", parent_tracer, msg); 51101.1Skamil 51111.13Schristos DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n", 51121.1Skamil TWAIT_FNAME); 51131.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 51141.1Skamil tracer); 51151.1Skamil 51161.1Skamil validate_status_exited(status, exitval_tracer); 51171.1Skamil 51181.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 51191.1Skamil TWAIT_FNAME); 51201.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 51211.1Skamil tracee); 51221.1Skamil 51231.77Skamil validate_status_signaled(status, SIGKILL, 0); 51241.1Skamil 51251.1Skamil msg_close(&parent_tracer); 51261.1Skamil msg_close(&parent_tracee); 51271.1Skamil} 51281.77Skamil 51291.77Skamil#define ATTACH_LWPINFO(test, threads) \ 51301.77SkamilATF_TC(test); \ 51311.77SkamilATF_TC_HEAD(test, tc) \ 51321.77Skamil{ \ 51331.77Skamil atf_tc_set_md_var(tc, "descr", \ 51341.77Skamil "Verify LWPINFO with the child with " #threads \ 51351.77Skamil " spawned extra threads (tracer is not the original " \ 51361.77Skamil "parent)"); \ 51371.77Skamil} \ 51381.77Skamil \ 51391.77SkamilATF_TC_BODY(test, tc) \ 51401.77Skamil{ \ 51411.77Skamil \ 51421.77Skamil attach_lwpinfo(threads); \ 51431.77Skamil} 51441.77Skamil 51451.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0) 51461.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1) 51471.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2) 51481.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3) 51491.1Skamil#endif 51501.1Skamil 51511.77Skamil/// ---------------------------------------------------------------------------- 51521.77Skamil 51531.1Skamilstatic void 51541.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught) 51551.1Skamil{ 51561.1Skamil const int exitval = 5; 51571.1Skamil const int sigval = SIGINT; 51581.1Skamil const int sigfaked = SIGTRAP; 51591.1Skamil const int sicodefaked = TRAP_BRKPT; 51601.1Skamil pid_t child, wpid; 51611.1Skamil struct sigaction sa; 51621.1Skamil#if defined(TWAIT_HAVE_STATUS) 51631.1Skamil int status; 51641.1Skamil#endif 51651.1Skamil struct ptrace_siginfo info; 51661.1Skamil memset(&info, 0, sizeof(info)); 51671.1Skamil 51681.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 51691.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 51701.1Skamil if (child == 0) { 51711.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 51721.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 51731.1Skamil 51741.79Skamil sa.sa_sigaction = sah; 51751.1Skamil sa.sa_flags = SA_SIGINFO; 51761.1Skamil sigemptyset(&sa.sa_mask); 51771.1Skamil 51781.79Skamil FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL) 51791.79Skamil != -1); 51801.1Skamil 51811.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 51821.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 51831.1Skamil 51841.79Skamil FORKEE_ASSERT_EQ(*signal_caught, 1); 51851.1Skamil 51861.13Schristos DPRINTF("Before exiting of the child process\n"); 51871.1Skamil _exit(exitval); 51881.1Skamil } 51891.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 51901.1Skamil 51911.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51921.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 51931.1Skamil 51941.1Skamil validate_status_stopped(status, sigval); 51951.1Skamil 51961.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 51971.61Skre SYSCALL_REQUIRE( 51981.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 51991.1Skamil 52001.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 52011.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 52021.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 52031.1Skamil info.psi_siginfo.si_errno); 52041.1Skamil 52051.79Skamil if (faked) { 52061.79Skamil DPRINTF("Before setting new faked signal to signo=%d " 52071.79Skamil "si_code=%d\n", sigfaked, sicodefaked); 52081.79Skamil info.psi_siginfo.si_signo = sigfaked; 52091.79Skamil info.psi_siginfo.si_code = sicodefaked; 52101.79Skamil } 52111.1Skamil 52121.13Schristos DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n"); 52131.61Skre SYSCALL_REQUIRE( 52141.61Skre ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1); 52151.1Skamil 52161.79Skamil if (faked) { 52171.79Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 52181.79Skamil "child\n"); 52191.79Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 52201.79Skamil sizeof(info)) != -1); 52211.1Skamil 52221.79Skamil DPRINTF("Before checking siginfo_t\n"); 52231.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked); 52241.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked); 52251.79Skamil } 52261.1Skamil 52271.13Schristos DPRINTF("Before resuming the child process where it left off and " 52281.1Skamil "without signal to be sent\n"); 52291.79Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 52301.79Skamil faked ? sigfaked : sigval) != -1); 52311.1Skamil 52321.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52331.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52341.1Skamil 52351.1Skamil validate_status_exited(status, exitval); 52361.1Skamil 52371.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52381.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 52391.1Skamil} 52401.1Skamil 52411.79Skamil#define PTRACE_SIGINFO(test, faked) \ 52421.79SkamilATF_TC(test); \ 52431.79SkamilATF_TC_HEAD(test, tc) \ 52441.79Skamil{ \ 52451.79Skamil atf_tc_set_md_var(tc, "descr", \ 52461.79Skamil "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls" \ 52471.79Skamil "with%s setting signal to new value", faked ? "" : "out"); \ 52481.79Skamil} \ 52491.79Skamil \ 52501.79Skamilstatic int test##_caught = 0; \ 52511.79Skamil \ 52521.79Skamilstatic void \ 52531.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx) \ 52541.79Skamil{ \ 52551.79Skamil if (faked) { \ 52561.79Skamil FORKEE_ASSERT_EQ(sig, SIGTRAP); \ 52571.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP); \ 52581.79Skamil FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT); \ 52591.79Skamil } else { \ 52601.79Skamil FORKEE_ASSERT_EQ(sig, SIGINT); \ 52611.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGINT); \ 52621.79Skamil FORKEE_ASSERT_EQ(info->si_code, SI_LWP); \ 52631.79Skamil } \ 52641.79Skamil \ 52651.79Skamil ++ test##_caught; \ 52661.79Skamil} \ 52671.79Skamil \ 52681.79SkamilATF_TC_BODY(test, tc) \ 52691.79Skamil{ \ 52701.79Skamil \ 52711.79Skamil ptrace_siginfo(faked, test##_sighandler, & test##_caught); \ 52721.79Skamil} 52731.79Skamil 52741.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false) 52751.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true) 52761.79Skamil 52771.79Skamil/// ---------------------------------------------------------------------------- 52781.79Skamil 52791.97Skamilstatic void 52801.97Skamiltraceme_exec(bool masked, bool ignored) 52811.1Skamil{ 52821.1Skamil const int sigval = SIGTRAP; 52831.1Skamil pid_t child, wpid; 52841.1Skamil#if defined(TWAIT_HAVE_STATUS) 52851.1Skamil int status; 52861.1Skamil#endif 52871.97Skamil struct sigaction sa; 52881.97Skamil struct ptrace_siginfo info; 52891.97Skamil sigset_t intmask; 52901.97Skamil struct kinfo_proc2 kp; 52911.97Skamil size_t len = sizeof(kp); 52921.97Skamil 52931.97Skamil int name[6]; 52941.97Skamil const size_t namelen = __arraycount(name); 52951.97Skamil ki_sigset_t kp_sigmask; 52961.97Skamil ki_sigset_t kp_sigignore; 52971.1Skamil 52981.1Skamil memset(&info, 0, sizeof(info)); 52991.1Skamil 53001.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 53011.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 53021.1Skamil if (child == 0) { 53031.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 53041.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 53051.1Skamil 53061.97Skamil if (masked) { 53071.97Skamil sigemptyset(&intmask); 53081.97Skamil sigaddset(&intmask, sigval); 53091.97Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 53101.97Skamil } 53111.97Skamil 53121.97Skamil if (ignored) { 53131.97Skamil memset(&sa, 0, sizeof(sa)); 53141.97Skamil sa.sa_handler = SIG_IGN; 53151.97Skamil sigemptyset(&sa.sa_mask); 53161.97Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 53171.97Skamil } 53181.97Skamil 53191.13Schristos DPRINTF("Before calling execve(2) from child\n"); 53201.1Skamil execlp("/bin/echo", "/bin/echo", NULL); 53211.1Skamil 53221.1Skamil FORKEE_ASSERT(0 && "Not reached"); 53231.1Skamil } 53241.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 53251.1Skamil 53261.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53271.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 53281.1Skamil 53291.1Skamil validate_status_stopped(status, sigval); 53301.1Skamil 53311.97Skamil name[0] = CTL_KERN, 53321.97Skamil name[1] = KERN_PROC2, 53331.97Skamil name[2] = KERN_PROC_PID; 53341.97Skamil name[3] = getpid(); 53351.97Skamil name[4] = sizeof(kp); 53361.97Skamil name[5] = 1; 53371.97Skamil 53381.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 53391.97Skamil 53401.97Skamil if (masked) 53411.97Skamil kp_sigmask = kp.p_sigmask; 53421.97Skamil 53431.97Skamil if (ignored) 53441.97Skamil kp_sigignore = kp.p_sigignore; 53451.97Skamil 53461.97Skamil name[3] = getpid(); 53471.97Skamil 53481.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 53491.97Skamil 53501.97Skamil if (masked) { 53511.97Skamil DPRINTF("kp_sigmask=" 53521.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53531.97Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 53541.97Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 53551.97Skamil 53561.97Skamil DPRINTF("kp.p_sigmask=" 53571.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53581.97Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 53591.97Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 53601.97Skamil 53611.97Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 53621.97Skamil sizeof(kp_sigmask))); 53631.97Skamil } 53641.97Skamil 53651.97Skamil if (ignored) { 53661.97Skamil DPRINTF("kp_sigignore=" 53671.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53681.97Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 53691.97Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 53701.97Skamil 53711.97Skamil DPRINTF("kp.p_sigignore=" 53721.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53731.97Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 53741.97Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 53751.97Skamil 53761.97Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 53771.97Skamil sizeof(kp_sigignore))); 53781.97Skamil } 53791.97Skamil 53801.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 53811.61Skre SYSCALL_REQUIRE( 53821.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 53831.1Skamil 53841.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 53851.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 53861.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 53871.1Skamil info.psi_siginfo.si_errno); 53881.1Skamil 53891.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 53901.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 53911.1Skamil 53921.13Schristos DPRINTF("Before resuming the child process where it left off and " 53931.1Skamil "without signal to be sent\n"); 53941.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 53951.1Skamil 53961.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53971.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 53981.1Skamil 53991.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54001.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 54011.1Skamil} 54021.1Skamil 54031.97Skamil#define TRACEME_EXEC(test, masked, ignored) \ 54041.97SkamilATF_TC(test); \ 54051.97SkamilATF_TC_HEAD(test, tc) \ 54061.97Skamil{ \ 54071.97Skamil atf_tc_set_md_var(tc, "descr", \ 54081.97Skamil "Detect SIGTRAP TRAP_EXEC from " \ 54091.97Skamil "child%s%s", masked ? " with masked signal" : "", \ 54101.97Skamil masked ? " with ignored signal" : ""); \ 54111.97Skamil} \ 54121.97Skamil \ 54131.97SkamilATF_TC_BODY(test, tc) \ 54141.97Skamil{ \ 54151.97Skamil \ 54161.97Skamil traceme_exec(masked, ignored); \ 54171.97Skamil} 54181.97Skamil 54191.97SkamilTRACEME_EXEC(traceme_exec, false, false) 54201.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false) 54211.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true) 54221.97Skamil 54231.82Skamil/// ---------------------------------------------------------------------------- 54241.82Skamil 54251.83Skamilstatic volatile int done; 54261.1Skamil 54271.83Skamilstatic void * 54281.83Skamiltrace_threads_cb(void *arg __unused) 54291.1Skamil{ 54301.1Skamil 54311.83Skamil done++; 54321.83Skamil 54331.83Skamil while (done < 3) 54341.83Skamil continue; 54351.83Skamil 54361.83Skamil return NULL; 54371.1Skamil} 54381.1Skamil 54391.83Skamilstatic void 54401.83Skamiltrace_threads(bool trace_create, bool trace_exit) 54411.1Skamil{ 54421.1Skamil const int sigval = SIGSTOP; 54431.1Skamil pid_t child, wpid; 54441.1Skamil#if defined(TWAIT_HAVE_STATUS) 54451.1Skamil int status; 54461.1Skamil#endif 54471.1Skamil ptrace_state_t state; 54481.1Skamil const int slen = sizeof(state); 54491.1Skamil ptrace_event_t event; 54501.1Skamil const int elen = sizeof(event); 54511.83Skamil struct ptrace_siginfo info; 54521.83Skamil 54531.83Skamil pthread_t t[3]; 54541.83Skamil int rv; 54551.83Skamil size_t n; 54561.1Skamil lwpid_t lid; 54571.83Skamil 54581.83Skamil /* Track created and exited threads */ 54591.83Skamil bool traced_lwps[__arraycount(t)]; 54601.83Skamil 54611.128Skamil#if !TEST_LWP_ENABLED 54621.120Skamil if (trace_create || trace_exit) 54631.119Skamil atf_tc_skip("PR kern/51995"); 54641.128Skamil#endif 54651.1Skamil 54661.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 54671.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 54681.1Skamil if (child == 0) { 54691.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 54701.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 54711.1Skamil 54721.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 54731.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 54741.1Skamil 54751.83Skamil for (n = 0; n < __arraycount(t); n++) { 54761.83Skamil rv = pthread_create(&t[n], NULL, trace_threads_cb, 54771.83Skamil NULL); 54781.83Skamil FORKEE_ASSERT(rv == 0); 54791.83Skamil } 54801.1Skamil 54811.83Skamil for (n = 0; n < __arraycount(t); n++) { 54821.83Skamil rv = pthread_join(t[n], NULL); 54831.83Skamil FORKEE_ASSERT(rv == 0); 54841.83Skamil } 54851.1Skamil 54861.83Skamil /* 54871.83Skamil * There is race between _exit() and pthread_join() detaching 54881.83Skamil * a thread. For simplicity kill the process after detecting 54891.83Skamil * LWP events. 54901.83Skamil */ 54911.83Skamil while (true) 54921.83Skamil continue; 54931.1Skamil 54941.83Skamil FORKEE_ASSERT(0 && "Not reached"); 54951.1Skamil } 54961.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 54971.1Skamil 54981.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54991.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 55001.1Skamil 55011.1Skamil validate_status_stopped(status, sigval); 55021.1Skamil 55031.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 55041.83Skamil SYSCALL_REQUIRE( 55051.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55061.1Skamil 55071.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55081.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 55091.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55101.83Skamil info.psi_siginfo.si_errno); 55111.1Skamil 55121.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 55131.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 55141.1Skamil 55151.83Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 55161.83Skamil memset(&event, 0, sizeof(event)); 55171.83Skamil if (trace_create) 55181.83Skamil event.pe_set_event |= PTRACE_LWP_CREATE; 55191.83Skamil if (trace_exit) 55201.83Skamil event.pe_set_event |= PTRACE_LWP_EXIT; 55211.83Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 55221.1Skamil 55231.13Schristos DPRINTF("Before resuming the child process where it left off and " 55241.1Skamil "without signal to be sent\n"); 55251.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 55261.1Skamil 55271.83Skamil memset(traced_lwps, 0, sizeof(traced_lwps)); 55281.1Skamil 55291.83Skamil for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) { 55301.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 55311.83Skamil "SIGTRAP\n", TWAIT_FNAME); 55321.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 55331.83Skamil child); 55341.1Skamil 55351.83Skamil validate_status_stopped(status, SIGTRAP); 55361.1Skamil 55371.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 55381.83Skamil "child\n"); 55391.83Skamil SYSCALL_REQUIRE( 55401.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55411.1Skamil 55421.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55431.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 55441.83Skamil "si_errno=%#x\n", 55451.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55461.83Skamil info.psi_siginfo.si_errno); 55471.1Skamil 55481.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 55491.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 55501.1Skamil 55511.83Skamil SYSCALL_REQUIRE( 55521.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 55531.1Skamil 55541.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 55551.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 55561.1Skamil 55571.83Skamil lid = state.pe_lwp; 55581.83Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 55591.1Skamil 55601.83Skamil traced_lwps[lid - 1] = true; 55611.1Skamil 55621.83Skamil DPRINTF("Before resuming the child process where it left off " 55631.83Skamil "and without signal to be sent\n"); 55641.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 55651.83Skamil } 55661.1Skamil 55671.83Skamil for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) { 55681.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 55691.83Skamil "SIGTRAP\n", TWAIT_FNAME); 55701.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 55711.83Skamil child); 55721.1Skamil 55731.83Skamil validate_status_stopped(status, SIGTRAP); 55741.1Skamil 55751.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 55761.83Skamil "child\n"); 55771.83Skamil SYSCALL_REQUIRE( 55781.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55791.1Skamil 55801.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55811.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 55821.83Skamil "si_errno=%#x\n", 55831.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55841.83Skamil info.psi_siginfo.si_errno); 55851.1Skamil 55861.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 55871.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 55881.1Skamil 55891.83Skamil SYSCALL_REQUIRE( 55901.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 55911.1Skamil 55921.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 55931.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 55941.1Skamil 55951.83Skamil lid = state.pe_lwp; 55961.83Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 55971.1Skamil 55981.83Skamil if (trace_create) { 55991.83Skamil ATF_REQUIRE(traced_lwps[lid - 1] == true); 56001.83Skamil traced_lwps[lid - 1] = false; 56011.83Skamil } 56021.1Skamil 56031.83Skamil DPRINTF("Before resuming the child process where it left off " 56041.83Skamil "and without signal to be sent\n"); 56051.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56061.83Skamil } 56071.1Skamil 56081.83Skamil kill(child, SIGKILL); 56091.1Skamil 56101.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 56111.1Skamil TWAIT_FNAME); 56121.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56131.1Skamil 56141.83Skamil validate_status_signaled(status, SIGKILL, 0); 56151.1Skamil 56161.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 56171.1Skamil TWAIT_FNAME); 56181.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 56191.1Skamil} 56201.1Skamil 56211.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit) \ 56221.83SkamilATF_TC(test); \ 56231.83SkamilATF_TC_HEAD(test, tc) \ 56241.83Skamil{ \ 56251.83Skamil atf_tc_set_md_var(tc, "descr", \ 56261.83Skamil "Verify spawning threads with%s tracing LWP create and" \ 56271.83Skamil "with%s tracing LWP exit", trace_create ? "" : "out", \ 56281.83Skamil trace_exit ? "" : "out"); \ 56291.83Skamil} \ 56301.83Skamil \ 56311.83SkamilATF_TC_BODY(test, tc) \ 56321.83Skamil{ \ 56331.83Skamil \ 56341.83Skamil trace_threads(trace_create, trace_exit); \ 56351.83Skamil} 56361.83Skamil 56371.119SkamilTRACE_THREADS(trace_thread_nolwpevents, false, false) 56381.119SkamilTRACE_THREADS(trace_thread_lwpexit, false, true) 56391.119SkamilTRACE_THREADS(trace_thread_lwpcreate, true, false) 56401.119SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true) 56411.83Skamil 56421.83Skamil/// ---------------------------------------------------------------------------- 56431.83Skamil 56441.84SkamilATF_TC(signal_mask_unrelated); 56451.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc) 56461.1Skamil{ 56471.1Skamil atf_tc_set_md_var(tc, "descr", 56481.1Skamil "Verify that masking single unrelated signal does not stop tracer " 56491.1Skamil "from catching other signals"); 56501.1Skamil} 56511.1Skamil 56521.84SkamilATF_TC_BODY(signal_mask_unrelated, tc) 56531.1Skamil{ 56541.1Skamil const int exitval = 5; 56551.1Skamil const int sigval = SIGSTOP; 56561.1Skamil const int sigmasked = SIGTRAP; 56571.1Skamil const int signotmasked = SIGINT; 56581.1Skamil pid_t child, wpid; 56591.1Skamil#if defined(TWAIT_HAVE_STATUS) 56601.1Skamil int status; 56611.1Skamil#endif 56621.1Skamil sigset_t intmask; 56631.1Skamil 56641.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 56651.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 56661.1Skamil if (child == 0) { 56671.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 56681.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 56691.1Skamil 56701.1Skamil sigemptyset(&intmask); 56711.1Skamil sigaddset(&intmask, sigmasked); 56721.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 56731.1Skamil 56741.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 56751.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 56761.1Skamil 56771.13Schristos DPRINTF("Before raising %s from child\n", 56781.1Skamil strsignal(signotmasked)); 56791.1Skamil FORKEE_ASSERT(raise(signotmasked) == 0); 56801.1Skamil 56811.13Schristos DPRINTF("Before exiting of the child process\n"); 56821.1Skamil _exit(exitval); 56831.1Skamil } 56841.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 56851.1Skamil 56861.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56871.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56881.1Skamil 56891.1Skamil validate_status_stopped(status, sigval); 56901.1Skamil 56911.13Schristos DPRINTF("Before resuming the child process where it left off and " 56921.1Skamil "without signal to be sent\n"); 56931.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56941.1Skamil 56951.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56961.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56971.1Skamil 56981.1Skamil validate_status_stopped(status, signotmasked); 56991.1Skamil 57001.13Schristos DPRINTF("Before resuming the child process where it left off and " 57011.1Skamil "without signal to be sent\n"); 57021.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 57031.1Skamil 57041.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57051.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57061.1Skamil 57071.1Skamil validate_status_exited(status, exitval); 57081.1Skamil 57091.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57101.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 57111.1Skamil} 57121.1Skamil 57131.84Skamil/// ---------------------------------------------------------------------------- 57141.84Skamil 57151.1Skamil#if defined(TWAIT_HAVE_PID) 57161.99Skamilstatic void 57171.126Skamilfork2_body(const char *fn, bool masked, bool ignored) 57181.1Skamil{ 57191.1Skamil const int exitval = 5; 57201.126Skamil const int exitval2 = 0; /* Match exit status from /bin/echo */ 57211.1Skamil const int sigval = SIGSTOP; 57221.99Skamil pid_t child, child2 = 0, wpid; 57231.1Skamil#if defined(TWAIT_HAVE_STATUS) 57241.1Skamil int status; 57251.1Skamil#endif 57261.1Skamil ptrace_state_t state; 57271.1Skamil const int slen = sizeof(state); 57281.1Skamil ptrace_event_t event; 57291.1Skamil const int elen = sizeof(event); 57301.99Skamil struct sigaction sa; 57311.99Skamil struct ptrace_siginfo info; 57321.99Skamil sigset_t intmask; 57331.99Skamil struct kinfo_proc2 kp; 57341.99Skamil size_t len = sizeof(kp); 57351.99Skamil 57361.99Skamil int name[6]; 57371.99Skamil const size_t namelen = __arraycount(name); 57381.99Skamil ki_sigset_t kp_sigmask; 57391.99Skamil ki_sigset_t kp_sigignore; 57401.1Skamil 57411.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 57421.14Schristos 57431.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 57441.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 57451.1Skamil if (child == 0) { 57461.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 57471.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 57481.1Skamil 57491.99Skamil if (masked) { 57501.99Skamil sigemptyset(&intmask); 57511.99Skamil sigaddset(&intmask, SIGTRAP); 57521.99Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 57531.99Skamil } 57541.99Skamil 57551.99Skamil if (ignored) { 57561.99Skamil memset(&sa, 0, sizeof(sa)); 57571.99Skamil sa.sa_handler = SIG_IGN; 57581.99Skamil sigemptyset(&sa.sa_mask); 57591.99Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 57601.99Skamil } 57611.1Skamil 57621.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 57631.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 57641.1Skamil 57651.126Skamil if (strcmp(fn, "spawn") == 0) { 57661.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 57671.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 57681.126Skamil } else { 57691.126Skamil if (strcmp(fn, "fork") == 0) { 57701.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 57711.126Skamil } else { 57721.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 57731.126Skamil } 57741.126Skamil if (child2 == 0) 57751.126Skamil _exit(exitval2); 57761.126Skamil } 57771.1Skamil 57781.1Skamil FORKEE_REQUIRE_SUCCESS 57791.99Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 57801.1Skamil 57811.1Skamil forkee_status_exited(status, exitval2); 57821.1Skamil 57831.13Schristos DPRINTF("Before exiting of the child process\n"); 57841.1Skamil _exit(exitval); 57851.1Skamil } 57861.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 57871.1Skamil 57881.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57891.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57901.1Skamil 57911.1Skamil validate_status_stopped(status, sigval); 57921.1Skamil 57931.99Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 57941.99Skamil SYSCALL_REQUIRE( 57951.99Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 57961.99Skamil 57971.99Skamil DPRINTF("Before checking siginfo_t\n"); 57981.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 57991.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 58001.1Skamil 58011.99Skamil name[0] = CTL_KERN, 58021.99Skamil name[1] = KERN_PROC2, 58031.99Skamil name[2] = KERN_PROC_PID; 58041.99Skamil name[3] = child; 58051.99Skamil name[4] = sizeof(kp); 58061.99Skamil name[5] = 1; 58071.1Skamil 58081.99Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 58091.1Skamil 58101.99Skamil if (masked) 58111.99Skamil kp_sigmask = kp.p_sigmask; 58121.1Skamil 58131.99Skamil if (ignored) 58141.99Skamil kp_sigignore = kp.p_sigignore; 58151.1Skamil 58161.126Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 58171.126Skamil strcmp(fn, "spawn") == 0 ? "|PTRACE_POSIX_SPAWN" : "", 58181.126Skamil strcmp(fn, "fork") == 0 ? "|PTRACE_FORK" : "", 58191.126Skamil strcmp(fn, "vfork") == 0 ? "|PTRACE_VFORK" : "", 58201.126Skamil strcmp(fn, "vforkdone") == 0 ? "|PTRACE_VFORK_DONE" : "", child); 58211.99Skamil event.pe_set_event = 0; 58221.126Skamil if (strcmp(fn, "spawn") == 0) 58231.126Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 58241.126Skamil if (strcmp(fn, "fork") == 0) 58251.99Skamil event.pe_set_event |= PTRACE_FORK; 58261.126Skamil if (strcmp(fn, "vfork") == 0) 58271.99Skamil event.pe_set_event |= PTRACE_VFORK; 58281.126Skamil if (strcmp(fn, "vforkdone") == 0) 58291.99Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 58301.99Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 58311.1Skamil 58321.99Skamil DPRINTF("Before resuming the child process where it left off and " 58331.99Skamil "without signal to be sent\n"); 58341.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 58351.1Skamil 58361.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 58371.126Skamil strcmp(fn, "vfork") == 0) { 58381.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 58391.99Skamil child); 58401.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 58411.99Skamil child); 58421.1Skamil 58431.99Skamil validate_status_stopped(status, SIGTRAP); 58441.1Skamil 58451.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 58461.1Skamil 58471.99Skamil if (masked) { 58481.99Skamil DPRINTF("kp_sigmask=" 58491.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58501.99Skamil PRIx32 "\n", 58511.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 58521.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 58531.1Skamil 58541.99Skamil DPRINTF("kp.p_sigmask=" 58551.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58561.99Skamil PRIx32 "\n", 58571.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 58581.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 58591.1Skamil 58601.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 58611.99Skamil sizeof(kp_sigmask))); 58621.99Skamil } 58631.1Skamil 58641.99Skamil if (ignored) { 58651.99Skamil DPRINTF("kp_sigignore=" 58661.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58671.99Skamil PRIx32 "\n", 58681.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 58691.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 58701.1Skamil 58711.99Skamil DPRINTF("kp.p_sigignore=" 58721.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58731.99Skamil PRIx32 "\n", 58741.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 58751.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 58761.1Skamil 58771.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 58781.99Skamil sizeof(kp_sigignore))); 58791.99Skamil } 58801.1Skamil 58811.99Skamil SYSCALL_REQUIRE( 58821.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 58831.126Skamil if (strcmp(fn, "spawn") == 0) { 58841.126Skamil ATF_REQUIRE_EQ( 58851.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 58861.126Skamil PTRACE_POSIX_SPAWN); 58871.126Skamil } 58881.126Skamil if (strcmp(fn, "fork") == 0) { 58891.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 58901.99Skamil PTRACE_FORK); 58911.99Skamil } 58921.126Skamil if (strcmp(fn, "vfork") == 0) { 58931.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 58941.99Skamil PTRACE_VFORK); 58951.99Skamil } 58961.1Skamil 58971.99Skamil child2 = state.pe_other_pid; 58981.99Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 58991.1Skamil 59001.99Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 59011.99Skamil "%d\n", TWAIT_FNAME, child2, child); 59021.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 59031.99Skamil child2); 59041.1Skamil 59051.99Skamil validate_status_stopped(status, SIGTRAP); 59061.1Skamil 59071.99Skamil name[3] = child2; 59081.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 59091.1Skamil 59101.99Skamil if (masked) { 59111.99Skamil DPRINTF("kp_sigmask=" 59121.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59131.99Skamil PRIx32 "\n", 59141.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 59151.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 59161.1Skamil 59171.99Skamil DPRINTF("kp.p_sigmask=" 59181.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59191.99Skamil PRIx32 "\n", 59201.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 59211.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 59221.14Schristos 59231.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 59241.99Skamil sizeof(kp_sigmask))); 59251.99Skamil } 59261.1Skamil 59271.99Skamil if (ignored) { 59281.99Skamil DPRINTF("kp_sigignore=" 59291.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59301.99Skamil PRIx32 "\n", 59311.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 59321.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 59331.1Skamil 59341.99Skamil DPRINTF("kp.p_sigignore=" 59351.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59361.99Skamil PRIx32 "\n", 59371.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 59381.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 59391.1Skamil 59401.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 59411.99Skamil sizeof(kp_sigignore))); 59421.99Skamil } 59431.1Skamil 59441.99Skamil SYSCALL_REQUIRE( 59451.99Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 59461.126Skamil if (strcmp(fn, "spawn") == 0) { 59471.126Skamil ATF_REQUIRE_EQ( 59481.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 59491.126Skamil PTRACE_POSIX_SPAWN); 59501.126Skamil } 59511.126Skamil if (strcmp(fn, "fork") == 0) { 59521.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 59531.99Skamil PTRACE_FORK); 59541.99Skamil } 59551.126Skamil if (strcmp(fn, "vfork") == 0) { 59561.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 59571.99Skamil PTRACE_VFORK); 59581.99Skamil } 59591.1Skamil 59601.99Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 59611.1Skamil 59621.99Skamil DPRINTF("Before resuming the forkee process where it left off " 59631.99Skamil "and without signal to be sent\n"); 59641.99Skamil SYSCALL_REQUIRE( 59651.99Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 59661.1Skamil 59671.99Skamil DPRINTF("Before resuming the child process where it left off " 59681.99Skamil "and without signal to be sent\n"); 59691.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 59701.1Skamil } 59711.1Skamil 59721.126Skamil if (strcmp(fn, "vforkdone") == 0) { 59731.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 59741.99Skamil child); 59751.99Skamil TWAIT_REQUIRE_SUCCESS( 59761.99Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 59771.1Skamil 59781.99Skamil validate_status_stopped(status, SIGTRAP); 59791.1Skamil 59801.99Skamil name[3] = child; 59811.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 59821.1Skamil 59831.102Skamil /* 59841.102Skamil * SIGCHLD is now pending in the signal queue and 59851.102Skamil * the kernel presents it to userland as a masked signal. 59861.102Skamil */ 59871.102Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 59881.102Skamil 59891.99Skamil if (masked) { 59901.99Skamil DPRINTF("kp_sigmask=" 59911.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59921.99Skamil PRIx32 "\n", 59931.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 59941.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 59951.1Skamil 59961.99Skamil DPRINTF("kp.p_sigmask=" 59971.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59981.99Skamil PRIx32 "\n", 59991.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 60001.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 60011.1Skamil 60021.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 60031.99Skamil sizeof(kp_sigmask))); 60041.99Skamil } 60051.1Skamil 60061.99Skamil if (ignored) { 60071.99Skamil DPRINTF("kp_sigignore=" 60081.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60091.99Skamil PRIx32 "\n", 60101.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 60111.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 60121.1Skamil 60131.99Skamil DPRINTF("kp.p_sigignore=" 60141.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60151.99Skamil PRIx32 "\n", 60161.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 60171.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 60181.1Skamil 60191.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 60201.99Skamil sizeof(kp_sigignore))); 60211.99Skamil } 60221.1Skamil 60231.99Skamil SYSCALL_REQUIRE( 60241.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 60251.99Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 60261.1Skamil 60271.99Skamil child2 = state.pe_other_pid; 60281.99Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 60291.99Skamil child2); 60301.1Skamil 60311.99Skamil DPRINTF("Before resuming the child process where it left off " 60321.99Skamil "and without signal to be sent\n"); 60331.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60341.99Skamil } 60351.1Skamil 60361.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 60371.126Skamil strcmp(fn, "vfork") == 0) { 60381.99Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 60391.99Skamil "\n", TWAIT_FNAME); 60401.99Skamil TWAIT_REQUIRE_SUCCESS( 60411.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 60421.1Skamil 60431.99Skamil validate_status_exited(status, exitval2); 60441.1Skamil 60451.99Skamil DPRINTF("Before calling %s() for the forkee - expected no " 60461.99Skamil "process\n", TWAIT_FNAME); 60471.99Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 60481.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 60491.99Skamil } 60501.1Skamil 60511.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 60521.1Skamil "SIGCHLD\n", TWAIT_FNAME); 60531.57Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60541.1Skamil 60551.1Skamil validate_status_stopped(status, SIGCHLD); 60561.1Skamil 60571.57Skamil DPRINTF("Before resuming the child process where it left off and " 60581.1Skamil "without signal to be sent\n"); 60591.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60601.1Skamil 60611.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 60621.1Skamil TWAIT_FNAME); 60631.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60641.1Skamil 60651.1Skamil validate_status_exited(status, exitval); 60661.1Skamil 60671.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 60681.57Skamil TWAIT_FNAME); 60691.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 60701.1Skamil} 60711.1Skamil 60721.126Skamil#define FORK2_TEST(name,fn,masked,ignored) \ 60731.99SkamilATF_TC(name); \ 60741.99SkamilATF_TC_HEAD(name, tc) \ 60751.99Skamil{ \ 60761.126Skamil atf_tc_set_md_var(tc, "descr", "Verify that " fn " is caught " \ 60771.99Skamil "regardless of signal %s%s", \ 60781.99Skamil masked ? "masked" : "", ignored ? "ignored" : ""); \ 60791.99Skamil} \ 60801.99Skamil \ 60811.99SkamilATF_TC_BODY(name, tc) \ 60821.99Skamil{ \ 60831.99Skamil \ 60841.126Skamil fork2_body(fn, masked, ignored); \ 60851.1Skamil} 60861.1Skamil 60871.126SkamilFORK2_TEST(posix_spawn_singalmasked, "spawn", true, false) 60881.126SkamilFORK2_TEST(posix_spawn_singalignored, "spawn", false, true) 60891.126SkamilFORK2_TEST(fork_singalmasked, "fork", true, false) 60901.126SkamilFORK2_TEST(fork_singalignored, "fork", false, true) 60911.110Skamil#if TEST_VFORK_ENABLED 60921.126SkamilFORK2_TEST(vfork_singalmasked, "vfork", true, false) 60931.126SkamilFORK2_TEST(vfork_singalignored, "vfork", false, true) 60941.126SkamilFORK2_TEST(vforkdone_singalmasked, "vforkdone", true, false) 60951.126SkamilFORK2_TEST(vforkdone_singalignored, "vforkdone", false, true) 60961.1Skamil#endif 60971.110Skamil#endif 60981.1Skamil 60991.99Skamil/// ---------------------------------------------------------------------------- 61001.1Skamil 61011.83Skamilvolatile lwpid_t the_lwp_id = 0; 61021.83Skamil 61031.83Skamilstatic void 61041.83Skamillwp_main_func(void *arg) 61051.83Skamil{ 61061.83Skamil the_lwp_id = _lwp_self(); 61071.83Skamil _lwp_exit(); 61081.83Skamil} 61091.83Skamil 61101.1SkamilATF_TC(signal9); 61111.1SkamilATF_TC_HEAD(signal9, tc) 61121.1Skamil{ 61131.1Skamil atf_tc_set_md_var(tc, "descr", 61141.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 61151.1Skamil "catching PTRACE_LWP_CREATE breakpoint"); 61161.1Skamil} 61171.1Skamil 61181.1SkamilATF_TC_BODY(signal9, tc) 61191.1Skamil{ 61201.1Skamil const int exitval = 5; 61211.1Skamil const int sigval = SIGSTOP; 61221.1Skamil const int sigmasked = SIGTRAP; 61231.1Skamil pid_t child, wpid; 61241.1Skamil#if defined(TWAIT_HAVE_STATUS) 61251.1Skamil int status; 61261.1Skamil#endif 61271.1Skamil sigset_t intmask; 61281.1Skamil ptrace_state_t state; 61291.1Skamil const int slen = sizeof(state); 61301.1Skamil ptrace_event_t event; 61311.1Skamil const int elen = sizeof(event); 61321.1Skamil ucontext_t uc; 61331.1Skamil lwpid_t lid; 61341.1Skamil static const size_t ssize = 16*1024; 61351.1Skamil void *stack; 61361.1Skamil 61371.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 61381.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 61391.1Skamil if (child == 0) { 61401.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 61411.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 61421.1Skamil 61431.1Skamil sigemptyset(&intmask); 61441.1Skamil sigaddset(&intmask, sigmasked); 61451.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 61461.1Skamil 61471.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 61481.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 61491.1Skamil 61501.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 61511.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 61521.1Skamil 61531.13Schristos DPRINTF("Before making context for new lwp in child\n"); 61541.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 61551.1Skamil 61561.13Schristos DPRINTF("Before creating new in child\n"); 61571.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 61581.1Skamil 61591.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 61601.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 61611.1Skamil 61621.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 61631.1Skamil "are the same\n", lid, the_lwp_id); 61641.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 61651.1Skamil 61661.13Schristos DPRINTF("Before exiting of the child process\n"); 61671.1Skamil _exit(exitval); 61681.1Skamil } 61691.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 61701.1Skamil 61711.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 61721.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61731.1Skamil 61741.1Skamil validate_status_stopped(status, sigval); 61751.1Skamil 61761.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 61771.1Skamil event.pe_set_event = PTRACE_LWP_CREATE; 61781.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 61791.1Skamil 61801.13Schristos DPRINTF("Before resuming the child process where it left off and " 61811.1Skamil "without signal to be sent\n"); 61821.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 61831.1Skamil 61841.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 61851.1Skamil "SIGTRAP\n", TWAIT_FNAME); 61861.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61871.1Skamil 61881.1Skamil validate_status_stopped(status, sigmasked); 61891.1Skamil 61901.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 61911.1Skamil 61921.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE); 61931.1Skamil 61941.1Skamil lid = state.pe_lwp; 61951.13Schristos DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 61961.1Skamil 61971.13Schristos DPRINTF("Before resuming the child process where it left off and " 61981.1Skamil "without signal to be sent\n"); 61991.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 62001.1Skamil 62011.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 62021.1Skamil TWAIT_FNAME); 62031.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62041.1Skamil 62051.1Skamil validate_status_exited(status, exitval); 62061.1Skamil 62071.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 62081.1Skamil TWAIT_FNAME); 62091.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 62101.1Skamil} 62111.1Skamil 62121.1SkamilATF_TC(signal10); 62131.1SkamilATF_TC_HEAD(signal10, tc) 62141.1Skamil{ 62151.1Skamil atf_tc_set_md_var(tc, "descr", 62161.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 62171.1Skamil "catching PTRACE_LWP_EXIT breakpoint"); 62181.1Skamil} 62191.1Skamil 62201.1SkamilATF_TC_BODY(signal10, tc) 62211.1Skamil{ 62221.1Skamil const int exitval = 5; 62231.1Skamil const int sigval = SIGSTOP; 62241.1Skamil const int sigmasked = SIGTRAP; 62251.1Skamil pid_t child, wpid; 62261.1Skamil#if defined(TWAIT_HAVE_STATUS) 62271.1Skamil int status; 62281.1Skamil#endif 62291.1Skamil sigset_t intmask; 62301.1Skamil ptrace_state_t state; 62311.1Skamil const int slen = sizeof(state); 62321.1Skamil ptrace_event_t event; 62331.1Skamil const int elen = sizeof(event); 62341.1Skamil ucontext_t uc; 62351.1Skamil lwpid_t lid; 62361.1Skamil static const size_t ssize = 16*1024; 62371.1Skamil void *stack; 62381.1Skamil 62391.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 62401.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 62411.1Skamil if (child == 0) { 62421.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 62431.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 62441.1Skamil 62451.1Skamil sigemptyset(&intmask); 62461.1Skamil sigaddset(&intmask, sigmasked); 62471.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 62481.1Skamil 62491.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 62501.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 62511.1Skamil 62521.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 62531.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 62541.1Skamil 62551.13Schristos DPRINTF("Before making context for new lwp in child\n"); 62561.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 62571.1Skamil 62581.13Schristos DPRINTF("Before creating new in child\n"); 62591.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 62601.1Skamil 62611.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 62621.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 62631.1Skamil 62641.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 62651.1Skamil "are the same\n", lid, the_lwp_id); 62661.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 62671.1Skamil 62681.13Schristos DPRINTF("Before exiting of the child process\n"); 62691.1Skamil _exit(exitval); 62701.1Skamil } 62711.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 62721.1Skamil 62731.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 62741.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62751.1Skamil 62761.1Skamil validate_status_stopped(status, sigval); 62771.1Skamil 62781.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 62791.1Skamil event.pe_set_event = PTRACE_LWP_EXIT; 62801.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 62811.1Skamil 62821.13Schristos DPRINTF("Before resuming the child process where it left off and " 62831.1Skamil "without signal to be sent\n"); 62841.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 62851.1Skamil 62861.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 62871.1Skamil "SIGTRAP\n", TWAIT_FNAME); 62881.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62891.1Skamil 62901.1Skamil validate_status_stopped(status, sigmasked); 62911.1Skamil 62921.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 62931.1Skamil 62941.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT); 62951.1Skamil 62961.1Skamil lid = state.pe_lwp; 62971.13Schristos DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 62981.1Skamil 62991.13Schristos DPRINTF("Before resuming the child process where it left off and " 63001.1Skamil "without signal to be sent\n"); 63011.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63021.1Skamil 63031.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 63041.1Skamil TWAIT_FNAME); 63051.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63061.1Skamil 63071.1Skamil validate_status_exited(status, exitval); 63081.1Skamil 63091.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 63101.1Skamil TWAIT_FNAME); 63111.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 63121.1Skamil} 63131.1Skamil 63141.1Skamilstatic void 63151.1Skamillwp_main_stop(void *arg) 63161.1Skamil{ 63171.1Skamil the_lwp_id = _lwp_self(); 63181.1Skamil 63191.1Skamil raise(SIGTRAP); 63201.1Skamil 63211.1Skamil _lwp_exit(); 63221.1Skamil} 63231.1Skamil 63241.1SkamilATF_TC(suspend1); 63251.1SkamilATF_TC_HEAD(suspend1, tc) 63261.1Skamil{ 63271.1Skamil atf_tc_set_md_var(tc, "descr", 63281.1Skamil "Verify that a thread can be suspended by a debugger and later " 63291.1Skamil "resumed by a tracee"); 63301.1Skamil} 63311.1Skamil 63321.1SkamilATF_TC_BODY(suspend1, tc) 63331.1Skamil{ 63341.1Skamil const int exitval = 5; 63351.1Skamil const int sigval = SIGSTOP; 63361.1Skamil pid_t child, wpid; 63371.1Skamil#if defined(TWAIT_HAVE_STATUS) 63381.1Skamil int status; 63391.1Skamil#endif 63401.1Skamil ucontext_t uc; 63411.1Skamil lwpid_t lid; 63421.1Skamil static const size_t ssize = 16*1024; 63431.1Skamil void *stack; 63441.1Skamil struct ptrace_lwpinfo pl; 63451.1Skamil struct ptrace_siginfo psi; 63461.1Skamil volatile int go = 0; 63471.1Skamil 63481.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 63491.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 63501.1Skamil if (child == 0) { 63511.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 63521.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 63531.1Skamil 63541.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 63551.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 63561.1Skamil 63571.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 63581.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 63591.1Skamil 63601.13Schristos DPRINTF("Before making context for new lwp in child\n"); 63611.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 63621.1Skamil 63631.13Schristos DPRINTF("Before creating new in child\n"); 63641.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 63651.1Skamil 63661.1Skamil while (go == 0) 63671.1Skamil continue; 63681.1Skamil 63691.1Skamil raise(SIGINT); 63701.1Skamil 63711.1Skamil FORKEE_ASSERT(_lwp_continue(lid) == 0); 63721.1Skamil 63731.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 63741.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 63751.1Skamil 63761.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 63771.1Skamil "are the same\n", lid, the_lwp_id); 63781.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 63791.1Skamil 63801.13Schristos DPRINTF("Before exiting of the child process\n"); 63811.1Skamil _exit(exitval); 63821.1Skamil } 63831.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 63841.1Skamil 63851.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 63861.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63871.1Skamil 63881.1Skamil validate_status_stopped(status, sigval); 63891.1Skamil 63901.13Schristos DPRINTF("Before resuming the child process where it left off and " 63911.1Skamil "without signal to be sent\n"); 63921.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63931.1Skamil 63941.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 63951.1Skamil "SIGTRAP\n", TWAIT_FNAME); 63961.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63971.1Skamil 63981.1Skamil validate_status_stopped(status, SIGTRAP); 63991.1Skamil 64001.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 64011.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 64021.1Skamil 64031.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 64041.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 64051.1Skamil 64061.13Schristos DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n", 64071.1Skamil child, getpid()); 64081.13Schristos SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1); 64091.1Skamil 64101.13Schristos DPRINTF("Before resuming the child process where it left off and " 64111.1Skamil "without signal to be sent\n"); 64121.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64131.1Skamil 64141.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 64151.1Skamil "SIGINT\n", TWAIT_FNAME); 64161.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64171.1Skamil 64181.1Skamil validate_status_stopped(status, SIGINT); 64191.1Skamil 64201.1Skamil pl.pl_lwpid = 0; 64211.1Skamil 64221.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 64231.1Skamil while (pl.pl_lwpid != 0) { 64241.1Skamil 64251.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 64261.1Skamil switch (pl.pl_lwpid) { 64271.1Skamil case 1: 64281.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 64291.1Skamil break; 64301.1Skamil case 2: 64311.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 64321.1Skamil break; 64331.1Skamil } 64341.1Skamil } 64351.1Skamil 64361.13Schristos DPRINTF("Before resuming the child process where it left off and " 64371.1Skamil "without signal to be sent\n"); 64381.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64391.1Skamil 64401.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 64411.1Skamil TWAIT_FNAME); 64421.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64431.1Skamil 64441.1Skamil validate_status_exited(status, exitval); 64451.1Skamil 64461.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 64471.1Skamil TWAIT_FNAME); 64481.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 64491.1Skamil} 64501.1Skamil 64511.1SkamilATF_TC(suspend2); 64521.1SkamilATF_TC_HEAD(suspend2, tc) 64531.1Skamil{ 64541.1Skamil atf_tc_set_md_var(tc, "descr", 64551.1Skamil "Verify that the while the only thread within a process is " 64561.1Skamil "suspended, the whole process cannot be unstopped"); 64571.1Skamil} 64581.1Skamil 64591.1SkamilATF_TC_BODY(suspend2, tc) 64601.1Skamil{ 64611.1Skamil const int exitval = 5; 64621.1Skamil const int sigval = SIGSTOP; 64631.1Skamil pid_t child, wpid; 64641.1Skamil#if defined(TWAIT_HAVE_STATUS) 64651.1Skamil int status; 64661.1Skamil#endif 64671.1Skamil struct ptrace_siginfo psi; 64681.1Skamil 64691.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 64701.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 64711.1Skamil if (child == 0) { 64721.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 64731.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 64741.1Skamil 64751.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 64761.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 64771.1Skamil 64781.13Schristos DPRINTF("Before exiting of the child process\n"); 64791.1Skamil _exit(exitval); 64801.1Skamil } 64811.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 64821.1Skamil 64831.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 64841.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64851.1Skamil 64861.1Skamil validate_status_stopped(status, sigval); 64871.1Skamil 64881.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 64891.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 64901.1Skamil 64911.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 64921.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 64931.1Skamil 64941.13Schristos DPRINTF("Before resuming the child process where it left off and " 64951.1Skamil "without signal to be sent\n"); 64961.1Skamil ATF_REQUIRE_ERRNO(EDEADLK, 64971.1Skamil ptrace(PT_CONTINUE, child, (void *)1, 0) == -1); 64981.1Skamil 64991.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 65001.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 65011.1Skamil 65021.13Schristos DPRINTF("Before resuming the child process where it left off and " 65031.1Skamil "without signal to be sent\n"); 65041.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65051.1Skamil 65061.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 65071.1Skamil TWAIT_FNAME); 65081.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65091.1Skamil 65101.1Skamil validate_status_exited(status, exitval); 65111.1Skamil 65121.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 65131.1Skamil TWAIT_FNAME); 65141.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 65151.1Skamil} 65161.1Skamil 65171.1SkamilATF_TC(resume1); 65181.1SkamilATF_TC_HEAD(resume1, tc) 65191.1Skamil{ 65201.1Skamil atf_tc_set_md_var(tc, "descr", 65211.1Skamil "Verify that a thread can be suspended by a debugger and later " 65221.1Skamil "resumed by the debugger"); 65231.1Skamil} 65241.1Skamil 65251.1SkamilATF_TC_BODY(resume1, tc) 65261.1Skamil{ 65271.1Skamil struct msg_fds fds; 65281.1Skamil const int exitval = 5; 65291.1Skamil const int sigval = SIGSTOP; 65301.1Skamil pid_t child, wpid; 65311.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 65321.1Skamil#if defined(TWAIT_HAVE_STATUS) 65331.1Skamil int status; 65341.1Skamil#endif 65351.1Skamil ucontext_t uc; 65361.1Skamil lwpid_t lid; 65371.1Skamil static const size_t ssize = 16*1024; 65381.1Skamil void *stack; 65391.1Skamil struct ptrace_lwpinfo pl; 65401.1Skamil struct ptrace_siginfo psi; 65411.1Skamil 65421.13Schristos SYSCALL_REQUIRE(msg_open(&fds) == 0); 65431.1Skamil 65441.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 65451.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 65461.1Skamil if (child == 0) { 65471.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 65481.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 65491.1Skamil 65501.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 65511.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 65521.1Skamil 65531.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 65541.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 65551.1Skamil 65561.13Schristos DPRINTF("Before making context for new lwp in child\n"); 65571.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 65581.1Skamil 65591.13Schristos DPRINTF("Before creating new in child\n"); 65601.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 65611.1Skamil 65621.1Skamil CHILD_TO_PARENT("Message", fds, msg); 65631.1Skamil 65641.1Skamil raise(SIGINT); 65651.1Skamil 65661.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 65671.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 65681.1Skamil 65691.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 65701.1Skamil "are the same\n", lid, the_lwp_id); 65711.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 65721.1Skamil 65731.13Schristos DPRINTF("Before exiting of the child process\n"); 65741.1Skamil _exit(exitval); 65751.1Skamil } 65761.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 65771.1Skamil 65781.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65791.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65801.1Skamil 65811.1Skamil validate_status_stopped(status, sigval); 65821.1Skamil 65831.13Schristos DPRINTF("Before resuming the child process where it left off and " 65841.1Skamil "without signal to be sent\n"); 65851.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65861.1Skamil 65871.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 65881.1Skamil "SIGTRAP\n", TWAIT_FNAME); 65891.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65901.1Skamil 65911.1Skamil validate_status_stopped(status, SIGTRAP); 65921.1Skamil 65931.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 65941.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 65951.1Skamil 65961.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 65971.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 65981.1Skamil 65991.1Skamil PARENT_FROM_CHILD("Message", fds, msg); 66001.1Skamil 66011.13Schristos DPRINTF("Before resuming the child process where it left off and " 66021.1Skamil "without signal to be sent\n"); 66031.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66041.1Skamil 66051.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 66061.1Skamil "SIGINT\n", TWAIT_FNAME); 66071.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66081.1Skamil 66091.1Skamil validate_status_stopped(status, SIGINT); 66101.1Skamil 66111.1Skamil pl.pl_lwpid = 0; 66121.1Skamil 66131.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 66141.1Skamil while (pl.pl_lwpid != 0) { 66151.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 66161.1Skamil switch (pl.pl_lwpid) { 66171.1Skamil case 1: 66181.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 66191.1Skamil break; 66201.1Skamil case 2: 66211.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 66221.1Skamil break; 66231.1Skamil } 66241.1Skamil } 66251.1Skamil 66261.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 66271.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 66281.1Skamil 66291.13Schristos DPRINTF("Before resuming the child process where it left off and " 66301.1Skamil "without signal to be sent\n"); 66311.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66321.1Skamil 66331.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 66341.1Skamil TWAIT_FNAME); 66351.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66361.1Skamil 66371.1Skamil validate_status_exited(status, exitval); 66381.1Skamil 66391.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 66401.1Skamil TWAIT_FNAME); 66411.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 66421.1Skamil 66431.1Skamil msg_close(&fds); 66441.1Skamil} 66451.1Skamil 66461.1SkamilATF_TC(syscall1); 66471.1SkamilATF_TC_HEAD(syscall1, tc) 66481.1Skamil{ 66491.1Skamil atf_tc_set_md_var(tc, "descr", 66501.1Skamil "Verify that getpid(2) can be traced with PT_SYSCALL"); 66511.1Skamil} 66521.1Skamil 66531.1SkamilATF_TC_BODY(syscall1, tc) 66541.1Skamil{ 66551.1Skamil const int exitval = 5; 66561.1Skamil const int sigval = SIGSTOP; 66571.1Skamil pid_t child, wpid; 66581.1Skamil#if defined(TWAIT_HAVE_STATUS) 66591.1Skamil int status; 66601.1Skamil#endif 66611.1Skamil struct ptrace_siginfo info; 66621.1Skamil memset(&info, 0, sizeof(info)); 66631.1Skamil 66641.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 66651.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 66661.1Skamil if (child == 0) { 66671.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 66681.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 66691.1Skamil 66701.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 66711.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 66721.1Skamil 66731.1Skamil syscall(SYS_getpid); 66741.1Skamil 66751.13Schristos DPRINTF("Before exiting of the child process\n"); 66761.1Skamil _exit(exitval); 66771.1Skamil } 66781.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 66791.1Skamil 66801.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66811.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66821.1Skamil 66831.1Skamil validate_status_stopped(status, sigval); 66841.1Skamil 66851.13Schristos DPRINTF("Before resuming the child process where it left off and " 66861.1Skamil "without signal to be sent\n"); 66871.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 66881.1Skamil 66891.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66901.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66911.1Skamil 66921.1Skamil validate_status_stopped(status, SIGTRAP); 66931.1Skamil 66941.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 66951.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 66961.1Skamil 66971.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 66981.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 66991.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 67001.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE); 67011.1Skamil 67021.13Schristos DPRINTF("Before resuming the child process where it left off and " 67031.1Skamil "without signal to be sent\n"); 67041.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 67051.1Skamil 67061.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67071.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67081.1Skamil 67091.1Skamil validate_status_stopped(status, SIGTRAP); 67101.1Skamil 67111.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 67121.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 67131.1Skamil 67141.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 67151.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 67161.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 67171.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX); 67181.1Skamil 67191.13Schristos DPRINTF("Before resuming the child process where it left off and " 67201.1Skamil "without signal to be sent\n"); 67211.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 67221.1Skamil 67231.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67241.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67251.1Skamil 67261.1Skamil validate_status_exited(status, exitval); 67271.1Skamil 67281.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67291.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 67301.1Skamil} 67311.1Skamil 67321.1SkamilATF_TC(syscallemu1); 67331.1SkamilATF_TC_HEAD(syscallemu1, tc) 67341.1Skamil{ 67351.1Skamil atf_tc_set_md_var(tc, "descr", 67361.1Skamil "Verify that exit(2) can be intercepted with PT_SYSCALLEMU"); 67371.1Skamil} 67381.1Skamil 67391.1SkamilATF_TC_BODY(syscallemu1, tc) 67401.1Skamil{ 67411.1Skamil const int exitval = 5; 67421.1Skamil const int sigval = SIGSTOP; 67431.1Skamil pid_t child, wpid; 67441.1Skamil#if defined(TWAIT_HAVE_STATUS) 67451.1Skamil int status; 67461.1Skamil#endif 67471.1Skamil 67481.6Skamil#if defined(__sparc__) && !defined(__sparc64__) 67491.6Skamil /* syscallemu does not work on sparc (32-bit) */ 67501.6Skamil atf_tc_expect_fail("PR kern/52166"); 67511.6Skamil#endif 67521.6Skamil 67531.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 67541.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 67551.1Skamil if (child == 0) { 67561.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 67571.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 67581.1Skamil 67591.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 67601.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 67611.1Skamil 67621.1Skamil syscall(SYS_exit, 100); 67631.1Skamil 67641.13Schristos DPRINTF("Before exiting of the child process\n"); 67651.1Skamil _exit(exitval); 67661.1Skamil } 67671.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 67681.1Skamil 67691.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67701.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67711.1Skamil 67721.1Skamil validate_status_stopped(status, sigval); 67731.1Skamil 67741.13Schristos DPRINTF("Before resuming the child process where it left off and " 67751.1Skamil "without signal to be sent\n"); 67761.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 67771.1Skamil 67781.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67791.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67801.1Skamil 67811.1Skamil validate_status_stopped(status, SIGTRAP); 67821.1Skamil 67831.13Schristos DPRINTF("Set SYSCALLEMU for intercepted syscall\n"); 67841.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1); 67851.1Skamil 67861.13Schristos DPRINTF("Before resuming the child process where it left off and " 67871.1Skamil "without signal to be sent\n"); 67881.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 67891.1Skamil 67901.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67911.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67921.1Skamil 67931.1Skamil validate_status_stopped(status, SIGTRAP); 67941.1Skamil 67951.13Schristos DPRINTF("Before resuming the child process where it left off and " 67961.1Skamil "without signal to be sent\n"); 67971.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 67981.1Skamil 67991.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 68001.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68011.1Skamil 68021.1Skamil validate_status_exited(status, exitval); 68031.1Skamil 68041.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 68051.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 68061.1Skamil} 68071.1Skamil 68081.103Skamil/// ---------------------------------------------------------------------------- 68091.103Skamil 68101.106Skamilstatic void 68111.106Skamilclone_body(int flags, bool trackfork, bool trackvfork, 68121.106Skamil bool trackvforkdone) 68131.106Skamil{ 68141.106Skamil const int exitval = 5; 68151.106Skamil const int exitval2 = 15; 68161.106Skamil const int sigval = SIGSTOP; 68171.106Skamil pid_t child, child2 = 0, wpid; 68181.106Skamil#if defined(TWAIT_HAVE_STATUS) 68191.106Skamil int status; 68201.106Skamil#endif 68211.106Skamil ptrace_state_t state; 68221.106Skamil const int slen = sizeof(state); 68231.106Skamil ptrace_event_t event; 68241.106Skamil const int elen = sizeof(event); 68251.106Skamil 68261.106Skamil const size_t stack_size = 1024 * 1024; 68271.106Skamil void *stack, *stack_base; 68281.106Skamil 68291.106Skamil stack = malloc(stack_size); 68301.106Skamil ATF_REQUIRE(stack != NULL); 68311.106Skamil 68321.106Skamil#ifdef __MACHINE_STACK_GROWS_UP 68331.106Skamil stack_base = stack; 68341.106Skamil#else 68351.106Skamil stack_base = (char *)stack + stack_size; 68361.106Skamil#endif 68371.106Skamil 68381.106Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 68391.106Skamil SYSCALL_REQUIRE((child = fork()) != -1); 68401.106Skamil if (child == 0) { 68411.106Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 68421.106Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 68431.106Skamil 68441.106Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 68451.106Skamil FORKEE_ASSERT(raise(sigval) == 0); 68461.106Skamil 68471.106Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 68481.106Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 68491.106Skamil 68501.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 68511.106Skamil child2); 68521.106Skamil 68531.106Skamil // XXX WALLSIG? 68541.106Skamil FORKEE_REQUIRE_SUCCESS 68551.106Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 68561.106Skamil 68571.106Skamil forkee_status_exited(status, exitval2); 68581.106Skamil 68591.106Skamil DPRINTF("Before exiting of the child process\n"); 68601.106Skamil _exit(exitval); 68611.106Skamil } 68621.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 68631.106Skamil 68641.106Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 68651.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68661.106Skamil 68671.106Skamil validate_status_stopped(status, sigval); 68681.106Skamil 68691.106Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 68701.106Skamil trackfork ? "|PTRACE_FORK" : "", 68711.106Skamil trackvfork ? "|PTRACE_VFORK" : "", 68721.106Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 68731.106Skamil event.pe_set_event = 0; 68741.106Skamil if (trackfork) 68751.106Skamil event.pe_set_event |= PTRACE_FORK; 68761.106Skamil if (trackvfork) 68771.106Skamil event.pe_set_event |= PTRACE_VFORK; 68781.106Skamil if (trackvforkdone) 68791.106Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 68801.106Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 68811.106Skamil 68821.106Skamil DPRINTF("Before resuming the child process where it left off and " 68831.106Skamil "without signal to be sent\n"); 68841.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68851.106Skamil 68861.106Skamil#if defined(TWAIT_HAVE_PID) 68871.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 68881.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 68891.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 68901.106Skamil child); 68911.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 68921.106Skamil child); 68931.106Skamil 68941.106Skamil validate_status_stopped(status, SIGTRAP); 68951.106Skamil 68961.106Skamil SYSCALL_REQUIRE( 68971.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 68981.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 68991.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 69001.106Skamil PTRACE_FORK); 69011.106Skamil } 69021.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 69031.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 69041.106Skamil PTRACE_VFORK); 69051.106Skamil } 69061.106Skamil 69071.106Skamil child2 = state.pe_other_pid; 69081.106Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 69091.106Skamil 69101.106Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 69111.106Skamil "%d\n", TWAIT_FNAME, child2, child); 69121.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 69131.106Skamil child2); 69141.106Skamil 69151.106Skamil validate_status_stopped(status, SIGTRAP); 69161.106Skamil 69171.106Skamil SYSCALL_REQUIRE( 69181.106Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 69191.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 69201.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 69211.106Skamil PTRACE_FORK); 69221.106Skamil } 69231.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 69241.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 69251.106Skamil PTRACE_VFORK); 69261.106Skamil } 69271.106Skamil 69281.106Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 69291.106Skamil 69301.106Skamil DPRINTF("Before resuming the forkee process where it left off " 69311.106Skamil "and without signal to be sent\n"); 69321.106Skamil SYSCALL_REQUIRE( 69331.106Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 69341.106Skamil 69351.106Skamil DPRINTF("Before resuming the child process where it left off " 69361.106Skamil "and without signal to be sent\n"); 69371.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69381.106Skamil } 69391.106Skamil#endif 69401.106Skamil 69411.106Skamil if (trackvforkdone && (flags & CLONE_VFORK)) { 69421.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 69431.106Skamil child); 69441.106Skamil TWAIT_REQUIRE_SUCCESS( 69451.106Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 69461.106Skamil 69471.106Skamil validate_status_stopped(status, SIGTRAP); 69481.106Skamil 69491.106Skamil SYSCALL_REQUIRE( 69501.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 69511.106Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 69521.106Skamil 69531.106Skamil child2 = state.pe_other_pid; 69541.106Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 69551.106Skamil child2); 69561.106Skamil 69571.106Skamil DPRINTF("Before resuming the child process where it left off " 69581.106Skamil "and without signal to be sent\n"); 69591.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69601.106Skamil } 69611.106Skamil 69621.103Skamil#if defined(TWAIT_HAVE_PID) 69631.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 69641.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 69651.106Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 69661.106Skamil "\n", TWAIT_FNAME); 69671.106Skamil TWAIT_REQUIRE_SUCCESS( 69681.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 69691.106Skamil 69701.106Skamil validate_status_exited(status, exitval2); 69711.106Skamil 69721.106Skamil DPRINTF("Before calling %s() for the forkee - expected no " 69731.106Skamil "process\n", TWAIT_FNAME); 69741.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 69751.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 69761.106Skamil } 69771.106Skamil#endif 69781.106Skamil 69791.106Skamil DPRINTF("Before calling %s() for the child - expected stopped " 69801.106Skamil "SIGCHLD\n", TWAIT_FNAME); 69811.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 69821.106Skamil 69831.106Skamil validate_status_stopped(status, SIGCHLD); 69841.106Skamil 69851.106Skamil DPRINTF("Before resuming the child process where it left off and " 69861.106Skamil "without signal to be sent\n"); 69871.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69881.106Skamil 69891.106Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 69901.106Skamil TWAIT_FNAME); 69911.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 69921.106Skamil 69931.106Skamil validate_status_exited(status, exitval); 69941.103Skamil 69951.106Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 69961.106Skamil TWAIT_FNAME); 69971.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 69981.106Skamil} 69991.103Skamil 70001.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone) \ 70011.106SkamilATF_TC(name); \ 70021.106SkamilATF_TC_HEAD(name, tc) \ 70031.106Skamil{ \ 70041.106Skamil atf_tc_set_md_var(tc, "descr", "Verify clone(%s) " \ 70051.106Skamil "called with 0%s%s%s in EVENT_MASK", \ 70061.106Skamil #flags, \ 70071.106Skamil tfork ? "|PTRACE_FORK" : "", \ 70081.106Skamil tvfork ? "|PTRACE_VFORK" : "", \ 70091.106Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 70101.106Skamil} \ 70111.106Skamil \ 70121.106SkamilATF_TC_BODY(name, tc) \ 70131.106Skamil{ \ 70141.106Skamil \ 70151.106Skamil clone_body(flags, tfork, tvfork, tvforkdone); \ 70161.103Skamil} 70171.103Skamil 70181.106SkamilCLONE_TEST(clone1, 0, false, false, false) 70191.106Skamil#if defined(TWAIT_HAVE_PID) 70201.106SkamilCLONE_TEST(clone2, 0, true, false, false) 70211.106SkamilCLONE_TEST(clone3, 0, false, true, false) 70221.106SkamilCLONE_TEST(clone4, 0, true, true, false) 70231.106Skamil#endif 70241.106SkamilCLONE_TEST(clone5, 0, false, false, true) 70251.106Skamil#if defined(TWAIT_HAVE_PID) 70261.106SkamilCLONE_TEST(clone6, 0, true, false, true) 70271.106SkamilCLONE_TEST(clone7, 0, false, true, true) 70281.106SkamilCLONE_TEST(clone8, 0, true, true, true) 70291.106Skamil#endif 70301.106Skamil 70311.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false) 70321.106Skamil#if defined(TWAIT_HAVE_PID) 70331.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false) 70341.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false) 70351.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false) 70361.106Skamil#endif 70371.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true) 70381.106Skamil#if defined(TWAIT_HAVE_PID) 70391.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true) 70401.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true) 70411.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true) 70421.106Skamil#endif 70431.106Skamil 70441.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false) 70451.106Skamil#if defined(TWAIT_HAVE_PID) 70461.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false) 70471.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false) 70481.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false) 70491.106Skamil#endif 70501.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true) 70511.106Skamil#if defined(TWAIT_HAVE_PID) 70521.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true) 70531.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true) 70541.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true) 70551.106Skamil#endif 70561.106Skamil 70571.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false) 70581.106Skamil#if defined(TWAIT_HAVE_PID) 70591.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false) 70601.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false) 70611.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false) 70621.106Skamil#endif 70631.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true) 70641.106Skamil#if defined(TWAIT_HAVE_PID) 70651.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true) 70661.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true) 70671.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true) 70681.106Skamil#endif 70691.106Skamil 70701.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false) 70711.106Skamil#if defined(TWAIT_HAVE_PID) 70721.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false) 70731.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false) 70741.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false) 70751.106Skamil#endif 70761.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true) 70771.106Skamil#if defined(TWAIT_HAVE_PID) 70781.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true) 70791.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true) 70801.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true) 70811.106Skamil#endif 70821.106Skamil 70831.110Skamil#if TEST_VFORK_ENABLED 70841.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false) 70851.106Skamil#if defined(TWAIT_HAVE_PID) 70861.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false) 70871.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false) 70881.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false) 70891.106Skamil#endif 70901.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true) 70911.106Skamil#if defined(TWAIT_HAVE_PID) 70921.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true) 70931.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true) 70941.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true) 70951.106Skamil#endif 70961.110Skamil#endif 70971.106Skamil 70981.106Skamil/// ---------------------------------------------------------------------------- 70991.106Skamil 71001.106Skamil#if defined(TWAIT_HAVE_PID) 71011.103Skamilstatic void 71021.106Skamilclone_body2(int flags, bool masked, bool ignored) 71031.103Skamil{ 71041.103Skamil const int exitval = 5; 71051.103Skamil const int exitval2 = 15; 71061.103Skamil const int sigval = SIGSTOP; 71071.103Skamil pid_t child, child2 = 0, wpid; 71081.103Skamil#if defined(TWAIT_HAVE_STATUS) 71091.103Skamil int status; 71101.103Skamil#endif 71111.103Skamil ptrace_state_t state; 71121.103Skamil const int slen = sizeof(state); 71131.103Skamil ptrace_event_t event; 71141.103Skamil const int elen = sizeof(event); 71151.103Skamil struct sigaction sa; 71161.103Skamil struct ptrace_siginfo info; 71171.103Skamil sigset_t intmask; 71181.103Skamil struct kinfo_proc2 kp; 71191.103Skamil size_t len = sizeof(kp); 71201.103Skamil 71211.103Skamil int name[6]; 71221.103Skamil const size_t namelen = __arraycount(name); 71231.103Skamil ki_sigset_t kp_sigmask; 71241.103Skamil ki_sigset_t kp_sigignore; 71251.103Skamil 71261.103Skamil const size_t stack_size = 1024 * 1024; 71271.103Skamil void *stack, *stack_base; 71281.103Skamil 71291.103Skamil stack = malloc(stack_size); 71301.103Skamil ATF_REQUIRE(stack != NULL); 71311.103Skamil 71321.103Skamil#ifdef __MACHINE_STACK_GROWS_UP 71331.103Skamil stack_base = stack; 71341.103Skamil#else 71351.103Skamil stack_base = (char *)stack + stack_size; 71361.103Skamil#endif 71371.103Skamil 71381.103Skamil SYSCALL_REQUIRE((child = fork()) != -1); 71391.103Skamil if (child == 0) { 71401.103Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 71411.103Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 71421.103Skamil 71431.103Skamil if (masked) { 71441.103Skamil sigemptyset(&intmask); 71451.103Skamil sigaddset(&intmask, SIGTRAP); 71461.103Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 71471.103Skamil } 71481.103Skamil 71491.103Skamil if (ignored) { 71501.103Skamil memset(&sa, 0, sizeof(sa)); 71511.103Skamil sa.sa_handler = SIG_IGN; 71521.103Skamil sigemptyset(&sa.sa_mask); 71531.103Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 71541.103Skamil } 71551.103Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 71561.103Skamil FORKEE_ASSERT(raise(sigval) == 0); 71571.103Skamil 71581.103Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 71591.103Skamil flags); 71601.103Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 71611.103Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 71621.103Skamil 71631.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 71641.103Skamil child2); 71651.103Skamil 71661.103Skamil // XXX WALLSIG? 71671.103Skamil FORKEE_REQUIRE_SUCCESS 71681.103Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 71691.103Skamil 71701.103Skamil forkee_status_exited(status, exitval2); 71711.103Skamil 71721.103Skamil DPRINTF("Before exiting of the child process\n"); 71731.103Skamil _exit(exitval); 71741.103Skamil } 71751.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 71761.103Skamil 71771.103Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 71781.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 71791.103Skamil 71801.103Skamil validate_status_stopped(status, sigval); 71811.103Skamil 71821.103Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 71831.103Skamil SYSCALL_REQUIRE( 71841.103Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 71851.103Skamil 71861.103Skamil DPRINTF("Before checking siginfo_t\n"); 71871.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 71881.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 71891.103Skamil 71901.103Skamil name[0] = CTL_KERN, 71911.103Skamil name[1] = KERN_PROC2, 71921.103Skamil name[2] = KERN_PROC_PID; 71931.103Skamil name[3] = child; 71941.103Skamil name[4] = sizeof(kp); 71951.103Skamil name[5] = 1; 71961.103Skamil 71971.103Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 71981.103Skamil 71991.103Skamil if (masked) 72001.103Skamil kp_sigmask = kp.p_sigmask; 72011.103Skamil 72021.103Skamil if (ignored) 72031.103Skamil kp_sigignore = kp.p_sigignore; 72041.103Skamil 72051.103Skamil DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in " 72061.103Skamil "EVENT_MASK for the child %d\n", child); 72071.103Skamil event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE; 72081.103Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 72091.103Skamil 72101.103Skamil DPRINTF("Before resuming the child process where it left off and " 72111.103Skamil "without signal to be sent\n"); 72121.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 72131.103Skamil 72141.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 72151.103Skamil child); 72161.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 72171.103Skamil child); 72181.103Skamil 72191.103Skamil validate_status_stopped(status, SIGTRAP); 72201.103Skamil 72211.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 72221.103Skamil 72231.103Skamil if (masked) { 72241.103Skamil DPRINTF("kp_sigmask=" 72251.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72261.103Skamil PRIx32 "\n", 72271.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 72281.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 72291.103Skamil 72301.103Skamil DPRINTF("kp.p_sigmask=" 72311.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72321.103Skamil PRIx32 "\n", 72331.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 72341.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 72351.103Skamil 72361.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 72371.103Skamil sizeof(kp_sigmask))); 72381.103Skamil } 72391.103Skamil 72401.103Skamil if (ignored) { 72411.103Skamil DPRINTF("kp_sigignore=" 72421.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72431.103Skamil PRIx32 "\n", 72441.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 72451.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 72461.103Skamil 72471.103Skamil DPRINTF("kp.p_sigignore=" 72481.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72491.103Skamil PRIx32 "\n", 72501.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 72511.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 72521.103Skamil 72531.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 72541.103Skamil sizeof(kp_sigignore))); 72551.103Skamil } 72561.103Skamil 72571.103Skamil SYSCALL_REQUIRE( 72581.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 72591.103Skamil DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event, 72601.103Skamil child2); 72611.103Skamil if (!(flags & CLONE_VFORK)) { 72621.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 72631.103Skamil PTRACE_FORK); 72641.103Skamil } else { 72651.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 72661.103Skamil PTRACE_VFORK); 72671.103Skamil } 72681.103Skamil 72691.103Skamil child2 = state.pe_other_pid; 72701.103Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 72711.103Skamil 72721.103Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 72731.103Skamil "%d\n", TWAIT_FNAME, child2, child); 72741.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 72751.103Skamil child2); 72761.103Skamil 72771.103Skamil validate_status_stopped(status, SIGTRAP); 72781.103Skamil 72791.103Skamil name[3] = child2; 72801.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 72811.103Skamil 72821.103Skamil if (masked) { 72831.103Skamil DPRINTF("kp_sigmask=" 72841.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72851.103Skamil PRIx32 "\n", 72861.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 72871.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 72881.103Skamil 72891.103Skamil DPRINTF("kp.p_sigmask=" 72901.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72911.103Skamil PRIx32 "\n", 72921.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 72931.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 72941.103Skamil 72951.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 72961.103Skamil sizeof(kp_sigmask))); 72971.103Skamil } 72981.103Skamil 72991.103Skamil if (ignored) { 73001.103Skamil DPRINTF("kp_sigignore=" 73011.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73021.103Skamil PRIx32 "\n", 73031.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 73041.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 73051.103Skamil 73061.103Skamil DPRINTF("kp.p_sigignore=" 73071.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73081.103Skamil PRIx32 "\n", 73091.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 73101.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 73111.103Skamil 73121.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 73131.103Skamil sizeof(kp_sigignore))); 73141.103Skamil } 73151.103Skamil 73161.103Skamil SYSCALL_REQUIRE( 73171.103Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 73181.103Skamil if (!(flags & CLONE_VFORK)) { 73191.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 73201.103Skamil PTRACE_FORK); 73211.103Skamil } else { 73221.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 73231.103Skamil PTRACE_VFORK); 73241.103Skamil } 73251.103Skamil 73261.103Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 73271.103Skamil 73281.103Skamil DPRINTF("Before resuming the forkee process where it left off " 73291.103Skamil "and without signal to be sent\n"); 73301.103Skamil SYSCALL_REQUIRE( 73311.103Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 73321.103Skamil 73331.103Skamil DPRINTF("Before resuming the child process where it left off " 73341.103Skamil "and without signal to be sent\n"); 73351.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 73361.103Skamil 73371.103Skamil if (flags & CLONE_VFORK) { 73381.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 73391.103Skamil child); 73401.103Skamil TWAIT_REQUIRE_SUCCESS( 73411.103Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 73421.103Skamil 73431.103Skamil validate_status_stopped(status, SIGTRAP); 73441.103Skamil 73451.103Skamil name[3] = child; 73461.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 73471.103Skamil 73481.103Skamil /* 73491.103Skamil * SIGCHLD is now pending in the signal queue and 73501.103Skamil * the kernel presents it to userland as a masked signal. 73511.103Skamil */ 73521.103Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 73531.103Skamil 73541.103Skamil if (masked) { 73551.103Skamil DPRINTF("kp_sigmask=" 73561.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73571.103Skamil PRIx32 "\n", 73581.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 73591.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 73601.103Skamil 73611.103Skamil DPRINTF("kp.p_sigmask=" 73621.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73631.103Skamil PRIx32 "\n", 73641.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 73651.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 73661.103Skamil 73671.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 73681.103Skamil sizeof(kp_sigmask))); 73691.103Skamil } 73701.103Skamil 73711.103Skamil if (ignored) { 73721.103Skamil DPRINTF("kp_sigignore=" 73731.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73741.103Skamil PRIx32 "\n", 73751.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 73761.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 73771.103Skamil 73781.103Skamil DPRINTF("kp.p_sigignore=" 73791.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73801.103Skamil PRIx32 "\n", 73811.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 73821.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 73831.103Skamil 73841.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 73851.103Skamil sizeof(kp_sigignore))); 73861.103Skamil } 73871.103Skamil 73881.103Skamil SYSCALL_REQUIRE( 73891.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 73901.103Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 73911.103Skamil 73921.103Skamil child2 = state.pe_other_pid; 73931.103Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 73941.103Skamil child2); 73951.103Skamil 73961.103Skamil DPRINTF("Before resuming the child process where it left off " 73971.103Skamil "and without signal to be sent\n"); 73981.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 73991.103Skamil } 74001.103Skamil 74011.103Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 74021.103Skamil "\n", TWAIT_FNAME); 74031.103Skamil TWAIT_REQUIRE_SUCCESS( 74041.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 74051.103Skamil 74061.103Skamil validate_status_exited(status, exitval2); 74071.103Skamil 74081.103Skamil DPRINTF("Before calling %s() for the forkee - expected no " 74091.103Skamil "process\n", TWAIT_FNAME); 74101.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 74111.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 74121.103Skamil 74131.103Skamil DPRINTF("Before calling %s() for the child - expected stopped " 74141.103Skamil "SIGCHLD\n", TWAIT_FNAME); 74151.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74161.103Skamil 74171.103Skamil validate_status_stopped(status, SIGCHLD); 74181.103Skamil 74191.103Skamil DPRINTF("Before resuming the child process where it left off and " 74201.103Skamil "without signal to be sent\n"); 74211.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 74221.103Skamil 74231.103Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 74241.103Skamil TWAIT_FNAME); 74251.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74261.103Skamil 74271.103Skamil validate_status_exited(status, exitval); 74281.103Skamil 74291.103Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 74301.103Skamil TWAIT_FNAME); 74311.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 74321.103Skamil} 74331.103Skamil 74341.106Skamil#define CLONE_TEST2(name,flags,masked,ignored) \ 74351.103SkamilATF_TC(name); \ 74361.103SkamilATF_TC_HEAD(name, tc) \ 74371.103Skamil{ \ 74381.103Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\ 74391.103Skamil " regardless of signal %s%s", \ 74401.103Skamil #flags, masked ? "masked" : "", ignored ? "ignored" : ""); \ 74411.103Skamil} \ 74421.103Skamil \ 74431.103SkamilATF_TC_BODY(name, tc) \ 74441.103Skamil{ \ 74451.103Skamil \ 74461.106Skamil clone_body2(flags, masked, ignored); \ 74471.103Skamil} 74481.103Skamil 74491.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false) 74501.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true) 74511.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false) 74521.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true) 74531.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false) 74541.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true) 74551.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false) 74561.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true) 74571.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX 74581.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true) // XXX 74591.110Skamil#if TEST_VFORK_ENABLED 74601.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false) 74611.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true) 74621.103Skamil#endif 74631.110Skamil#endif 74641.103Skamil 74651.103Skamil/// ---------------------------------------------------------------------------- 74661.103Skamil 74671.111Skamil#if TEST_VFORK_ENABLED 74681.107Skamil#if defined(TWAIT_HAVE_PID) 74691.107Skamilstatic void 74701.107Skamiltraceme_vfork_clone_body(int flags) 74711.107Skamil{ 74721.107Skamil const int exitval = 5; 74731.107Skamil const int exitval2 = 15; 74741.107Skamil pid_t child, child2 = 0, wpid; 74751.107Skamil#if defined(TWAIT_HAVE_STATUS) 74761.107Skamil int status; 74771.107Skamil#endif 74781.107Skamil 74791.107Skamil const size_t stack_size = 1024 * 1024; 74801.107Skamil void *stack, *stack_base; 74811.107Skamil 74821.107Skamil stack = malloc(stack_size); 74831.107Skamil ATF_REQUIRE(stack != NULL); 74841.107Skamil 74851.107Skamil#ifdef __MACHINE_STACK_GROWS_UP 74861.107Skamil stack_base = stack; 74871.107Skamil#else 74881.107Skamil stack_base = (char *)stack + stack_size; 74891.107Skamil#endif 74901.107Skamil 74911.107Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 74921.107Skamil if (child == 0) { 74931.107Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 74941.107Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 74951.107Skamil 74961.107Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 74971.107Skamil flags); 74981.107Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 74991.107Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 75001.107Skamil 75011.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 75021.107Skamil child2); 75031.107Skamil 75041.107Skamil // XXX WALLSIG? 75051.107Skamil FORKEE_REQUIRE_SUCCESS 75061.107Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 75071.107Skamil 75081.107Skamil forkee_status_exited(status, exitval2); 75091.107Skamil 75101.107Skamil DPRINTF("Before exiting of the child process\n"); 75111.107Skamil _exit(exitval); 75121.107Skamil } 75131.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 75141.107Skamil 75151.107Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 75161.107Skamil TWAIT_FNAME); 75171.107Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75181.107Skamil 75191.107Skamil validate_status_exited(status, exitval); 75201.107Skamil 75211.107Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 75221.107Skamil TWAIT_FNAME); 75231.107Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 75241.107Skamil} 75251.107Skamil 75261.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags) \ 75271.107SkamilATF_TC(name); \ 75281.107SkamilATF_TC_HEAD(name, tc) \ 75291.107Skamil{ \ 75301.107Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is " \ 75311.107Skamil "handled correctly with vfork(2)ed tracer", \ 75321.107Skamil #flags); \ 75331.107Skamil} \ 75341.107Skamil \ 75351.107SkamilATF_TC_BODY(name, tc) \ 75361.107Skamil{ \ 75371.107Skamil \ 75381.107Skamil traceme_vfork_clone_body(flags); \ 75391.107Skamil} 75401.107Skamil 75411.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0) 75421.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM) 75431.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS) 75441.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES) 75451.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND) // XXX 75461.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK) 75471.107Skamil#endif 75481.110Skamil#endif 75491.107Skamil 75501.107Skamil/// ---------------------------------------------------------------------------- 75511.107Skamil 75521.122Skamilstatic void 75531.122Skamiluser_va0_disable(int operation) 75541.122Skamil{ 75551.122Skamil pid_t child, wpid; 75561.122Skamil#if defined(TWAIT_HAVE_STATUS) 75571.122Skamil int status; 75581.122Skamil#endif 75591.122Skamil const int sigval = SIGSTOP; 75601.122Skamil int rv; 75611.122Skamil 75621.122Skamil struct ptrace_siginfo info; 75631.122Skamil 75641.122Skamil if (get_user_va0_disable() == 0) 75651.122Skamil atf_tc_skip("vm.user_va0_disable is set to 0"); 75661.122Skamil 75671.122Skamil memset(&info, 0, sizeof(info)); 75681.122Skamil 75691.122Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 75701.122Skamil SYSCALL_REQUIRE((child = fork()) != -1); 75711.122Skamil if (child == 0) { 75721.122Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 75731.122Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 75741.122Skamil 75751.122Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 75761.122Skamil FORKEE_ASSERT(raise(sigval) == 0); 75771.122Skamil 75781.122Skamil /* NOTREACHED */ 75791.122Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 75801.122Skamil __unreachable(); 75811.122Skamil } 75821.122Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 75831.122Skamil 75841.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75851.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75861.122Skamil 75871.122Skamil validate_status_stopped(status, sigval); 75881.122Skamil 75891.122Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 75901.122Skamil "child\n"); 75911.122Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 75921.122Skamil sizeof(info)) != -1); 75931.122Skamil 75941.122Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 75951.122Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 75961.122Skamil "si_errno=%#x\n", 75971.122Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 75981.122Skamil info.psi_siginfo.si_errno); 75991.122Skamil 76001.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 76011.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 76021.122Skamil 76031.122Skamil DPRINTF("Before resuming the child process in PC=0x0 " 76041.122Skamil "and without signal to be sent\n"); 76051.122Skamil errno = 0; 76061.122Skamil rv = ptrace(operation, child, (void *)0, 0); 76071.122Skamil ATF_REQUIRE_EQ(errno, EINVAL); 76081.122Skamil ATF_REQUIRE_EQ(rv, -1); 76091.122Skamil 76101.122Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 76111.122Skamil 76121.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76131.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 76141.122Skamil validate_status_signaled(status, SIGKILL, 0); 76151.122Skamil 76161.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76171.122Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 76181.122Skamil} 76191.122Skamil 76201.122Skamil#define USER_VA0_DISABLE(test, operation) \ 76211.122SkamilATF_TC(test); \ 76221.122SkamilATF_TC_HEAD(test, tc) \ 76231.122Skamil{ \ 76241.122Skamil atf_tc_set_md_var(tc, "descr", \ 76251.122Skamil "Verify behavior of " #operation " with PC set to 0x0"); \ 76261.122Skamil} \ 76271.122Skamil \ 76281.122SkamilATF_TC_BODY(test, tc) \ 76291.122Skamil{ \ 76301.122Skamil \ 76311.122Skamil user_va0_disable(operation); \ 76321.122Skamil} 76331.122Skamil 76341.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE) 76351.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL) 76361.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH) 76371.122Skamil 76381.122Skamil/// ---------------------------------------------------------------------------- 76391.122Skamil 76401.1Skamil#include "t_ptrace_amd64_wait.h" 76411.1Skamil#include "t_ptrace_i386_wait.h" 76421.1Skamil#include "t_ptrace_x86_wait.h" 76431.1Skamil 76441.1SkamilATF_TP_ADD_TCS(tp) 76451.1Skamil{ 76461.1Skamil setvbuf(stdout, NULL, _IONBF, 0); 76471.1Skamil setvbuf(stderr, NULL, _IONBF, 0); 76481.33Skamil 76491.36Skamil ATF_TP_ADD_TC(tp, traceme_raise1); 76501.33Skamil ATF_TP_ADD_TC(tp, traceme_raise2); 76511.33Skamil ATF_TP_ADD_TC(tp, traceme_raise3); 76521.33Skamil ATF_TP_ADD_TC(tp, traceme_raise4); 76531.33Skamil ATF_TP_ADD_TC(tp, traceme_raise5); 76541.85Skamil ATF_TP_ADD_TC(tp, traceme_raise6); 76551.85Skamil ATF_TP_ADD_TC(tp, traceme_raise7); 76561.85Skamil ATF_TP_ADD_TC(tp, traceme_raise8); 76571.85Skamil ATF_TP_ADD_TC(tp, traceme_raise9); 76581.85Skamil ATF_TP_ADD_TC(tp, traceme_raise10); 76591.33Skamil 76601.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1); 76611.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2); 76621.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3); 76631.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4); 76641.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5); 76651.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6); 76661.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7); 76671.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8); 76681.87Skamil 76691.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1); 76701.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2); 76711.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3); 76721.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4); 76731.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5); 76741.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6); 76751.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7); 76761.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8); 76771.86Skamil 76781.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_trap); 76791.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_segv); 76801.71Skamil ATF_TP_ADD_TC(tp, traceme_crash_ill); 76811.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_fpe); 76821.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_bus); 76831.59Skamil 76841.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap); 76851.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv); 76861.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill); 76871.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe); 76881.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus); 76891.88Skamil 76901.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap); 76911.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv); 76921.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill); 76931.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe); 76941.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus); 76951.88Skamil 76961.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1); 76971.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2); 76981.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3); 76991.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4); 77001.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5); 77011.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6); 77021.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7); 77031.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8); 77041.50Skamil 77051.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1); 77061.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2); 77071.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3); 77081.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4); 77091.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5); 77101.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6); 77111.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7); 77121.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8); 77131.50Skamil 77141.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1); 77151.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2); 77161.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3); 77171.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4); 77181.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5); 77191.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6); 77201.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7); 77211.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8); 77221.50Skamil 77231.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1); 77241.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2); 77251.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3); 77261.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4); 77271.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5); 77281.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6); 77291.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7); 77301.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8); 77311.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9); 77321.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10); 77331.1Skamil 77341.37Skamil ATF_TP_ADD_TC(tp, traceme_pid1_parent); 77351.37Skamil 77361.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise1); 77371.46Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise2); 77381.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise3); 77391.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise4); 77401.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise5); 77411.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise6); 77421.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise7); 77431.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise8); 77441.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise9); 77451.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise10); 77461.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise11); 77471.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise12); 77481.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise13); 77491.40Skamil 77501.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap); 77511.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv); 77521.71Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill); 77531.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe); 77541.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus); 77551.41Skamil 77561.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap); 77571.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv); 77581.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill); 77591.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe); 77601.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus); 77611.92Skamil 77621.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap); 77631.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv); 77641.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill); 77651.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe); 77661.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus); 77671.92Skamil 77681.43Skamil ATF_TP_ADD_TC(tp, traceme_vfork_exec); 77691.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec); 77701.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec); 77711.43Skamil 77721.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap); 77731.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv); 77741.71Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill); 77751.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe); 77761.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus); 77771.59Skamil 77781.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77791.94Skamil unrelated_tracer_sees_signalmasked_crash_trap); 77801.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77811.94Skamil unrelated_tracer_sees_signalmasked_crash_segv); 77821.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77831.94Skamil unrelated_tracer_sees_signalmasked_crash_ill); 77841.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77851.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe); 77861.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77871.94Skamil unrelated_tracer_sees_signalmasked_crash_bus); 77881.94Skamil 77891.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77901.94Skamil unrelated_tracer_sees_signalignored_crash_trap); 77911.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77921.94Skamil unrelated_tracer_sees_signalignored_crash_segv); 77931.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77941.94Skamil unrelated_tracer_sees_signalignored_crash_ill); 77951.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77961.94Skamil unrelated_tracer_sees_signalignored_crash_fpe); 77971.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77981.94Skamil unrelated_tracer_sees_signalignored_crash_bus); 77991.94Skamil 78001.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent); 78011.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates); 78021.61Skre ATF_TP_ADD_TC_HAVE_PID(tp, 78031.61Skre unrelated_tracer_sees_terminaton_before_the_parent); 78041.67Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process); 78051.51Skamil 78061.51Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_child); 78071.66Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child); 78081.51Skamil 78091.51Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_parent); 78101.65Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent); 78111.51Skamil 78121.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 78131.51Skamil tracee_sees_its_original_parent_getppid); 78141.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 78151.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2); 78161.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 78171.51Skamil tracee_sees_its_original_parent_procfs_status); 78181.1Skamil 78191.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_empty); 78201.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_fork); 78211.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork); 78221.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done); 78231.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create); 78241.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit); 78251.125Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_posix_spawn); 78261.1Skamil 78271.31Skamil ATF_TP_ADD_TC(tp, fork1); 78281.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork2); 78291.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork3); 78301.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork4); 78311.31Skamil ATF_TP_ADD_TC(tp, fork5); 78321.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork6); 78331.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork7); 78341.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork8); 78351.125Skamil ATF_TP_ADD_TC(tp, fork9); 78361.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork10); 78371.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork11); 78381.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork12); 78391.125Skamil ATF_TP_ADD_TC(tp, fork13); 78401.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork14); 78411.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork15); 78421.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork16); 78431.31Skamil 78441.109Skamil#if TEST_VFORK_ENABLED 78451.31Skamil ATF_TP_ADD_TC(tp, vfork1); 78461.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork2); 78471.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork3); 78481.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork4); 78491.31Skamil ATF_TP_ADD_TC(tp, vfork5); 78501.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork6); 78511.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork7); 78521.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork8); 78531.125Skamil ATF_TP_ADD_TC(tp, vfork9); 78541.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork10); 78551.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork11); 78561.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork12); 78571.125Skamil ATF_TP_ADD_TC(tp, vfork13); 78581.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork14); 78591.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork15); 78601.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork16); 78611.116Skamil#endif 78621.1Skamil 78631.124Skamil ATF_TP_ADD_TC(tp, posix_spawn1); 78641.125Skamil ATF_TP_ADD_TC(tp, posix_spawn2); 78651.125Skamil ATF_TP_ADD_TC(tp, posix_spawn3); 78661.125Skamil ATF_TP_ADD_TC(tp, posix_spawn4); 78671.124Skamil ATF_TP_ADD_TC(tp, posix_spawn5); 78681.125Skamil ATF_TP_ADD_TC(tp, posix_spawn6); 78691.125Skamil ATF_TP_ADD_TC(tp, posix_spawn7); 78701.125Skamil ATF_TP_ADD_TC(tp, posix_spawn8); 78711.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn9); 78721.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn10); 78731.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn11); 78741.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn12); 78751.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn13); 78761.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn14); 78771.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn15); 78781.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn16); 78791.124Skamil 78801.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_detach_spawner); 78811.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_detach_forker); 78821.116Skamil#if TEST_VFORK_ENABLED 78831.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforker); 78841.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforkerdone); 78851.116Skamil#endif 78861.126Skamil 78871.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_kill_spawner); 78881.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_kill_forker); 78891.116Skamil#if TEST_VFORK_ENABLED 78901.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforker); 78911.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforkerdone); 78921.116Skamil#endif 78931.116Skamil 78941.116Skamil#if TEST_VFORK_ENABLED 78951.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_fork); 78961.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_vfork); 78971.109Skamil#endif 78981.108Skamil 78991.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8); 79001.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16); 79011.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32); 79021.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64); 79031.54Skamil 79041.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8); 79051.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16); 79061.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32); 79071.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64); 79081.54Skamil 79091.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8); 79101.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16); 79111.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32); 79121.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64); 79131.54Skamil 79141.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8); 79151.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16); 79161.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32); 79171.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64); 79181.54Skamil 79191.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d); 79201.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i); 79211.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d); 79221.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i); 79231.54Skamil 79241.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text); 79251.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text); 79261.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text); 79271.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text); 79281.54Skamil 79291.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text); 79301.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text); 79311.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text); 79321.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text); 79331.54Skamil 79341.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text); 79351.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text); 79361.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text); 79371.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text); 79381.54Skamil 79391.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text); 79401.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text); 79411.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text); 79421.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text); 79431.54Skamil 79441.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text); 79451.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text); 79461.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text); 79471.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text); 79481.1Skamil 79491.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv); 79501.1Skamil 79511.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i); 79521.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d); 79531.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i); 79541.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d); 79551.101Skamil 79561.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i); 79571.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d); 79581.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i); 79591.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d); 79601.101Skamil 79611.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv); 79621.101Skamil 79631.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i); 79641.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d); 79651.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i); 79661.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d); 79671.115Skamil 79681.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i); 79691.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d); 79701.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i); 79711.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d); 79721.115Skamil 79731.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1); 79741.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2); 79751.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3); 79761.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4); 79771.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5); 79781.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6); 79791.1Skamil 79801.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1); 79811.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2); 79821.1Skamil 79831.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step1); 79841.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step2); 79851.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step3); 79861.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step4); 79871.1Skamil 79881.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep1); 79891.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep2); 79901.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep3); 79911.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep4); 79921.2Skamil 79931.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked); 79941.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored); 79951.95Skamil 79961.1Skamil ATF_TP_ADD_TC(tp, kill1); 79971.1Skamil ATF_TP_ADD_TC(tp, kill2); 79981.75Skamil ATF_TP_ADD_TC(tp, kill3); 79991.1Skamil 80001.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0); 80011.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1); 80021.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2); 80031.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3); 80041.77Skamil 80051.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0); 80061.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1); 80071.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2); 80081.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3); 80091.1Skamil 80101.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_unmodified); 80111.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_faked); 80121.79Skamil 80131.82Skamil ATF_TP_ADD_TC(tp, traceme_exec); 80141.97Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_exec); 80151.97Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_exec); 80161.1Skamil 80171.119Skamil ATF_TP_ADD_TC(tp, trace_thread_nolwpevents); 80181.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpexit); 80191.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate); 80201.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit); 80211.1Skamil 80221.84Skamil ATF_TP_ADD_TC(tp, signal_mask_unrelated); 80231.84Skamil 80241.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalmasked); 80251.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalignored); 80261.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked); 80271.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored); 80281.109Skamil#if TEST_VFORK_ENABLED 80291.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked); 80301.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored); 80311.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked); 80321.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored); 80331.109Skamil#endif 80341.99Skamil 80351.1Skamil ATF_TP_ADD_TC(tp, signal9); 80361.1Skamil ATF_TP_ADD_TC(tp, signal10); 80371.1Skamil 80381.1Skamil ATF_TP_ADD_TC(tp, suspend1); 80391.1Skamil ATF_TP_ADD_TC(tp, suspend2); 80401.1Skamil 80411.1Skamil ATF_TP_ADD_TC(tp, resume1); 80421.1Skamil 80431.1Skamil ATF_TP_ADD_TC(tp, syscall1); 80441.1Skamil 80451.1Skamil ATF_TP_ADD_TC(tp, syscallemu1); 80461.1Skamil 80471.106Skamil ATF_TP_ADD_TC(tp, clone1); 80481.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone2); 80491.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone3); 80501.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone4); 80511.106Skamil ATF_TP_ADD_TC(tp, clone5); 80521.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone6); 80531.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone7); 80541.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone8); 80551.106Skamil 80561.106Skamil ATF_TP_ADD_TC(tp, clone_vm1); 80571.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2); 80581.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3); 80591.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4); 80601.106Skamil ATF_TP_ADD_TC(tp, clone_vm5); 80611.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6); 80621.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7); 80631.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8); 80641.106Skamil 80651.106Skamil ATF_TP_ADD_TC(tp, clone_fs1); 80661.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2); 80671.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3); 80681.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4); 80691.106Skamil ATF_TP_ADD_TC(tp, clone_fs5); 80701.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6); 80711.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7); 80721.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8); 80731.106Skamil 80741.106Skamil ATF_TP_ADD_TC(tp, clone_files1); 80751.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2); 80761.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3); 80771.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4); 80781.106Skamil ATF_TP_ADD_TC(tp, clone_files5); 80791.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6); 80801.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7); 80811.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8); 80821.106Skamil 80831.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand1); // XXX 80841.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX 80851.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX 80861.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX 80871.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand5); // XXX 80881.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX 80891.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX 80901.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX 80911.106Skamil 80921.109Skamil#if TEST_VFORK_ENABLED 80931.106Skamil ATF_TP_ADD_TC(tp, clone_vfork1); 80941.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2); 80951.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3); 80961.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4); 80971.106Skamil ATF_TP_ADD_TC(tp, clone_vfork5); 80981.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6); 80991.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7); 81001.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8); 81011.109Skamil#endif 81021.106Skamil 81031.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored); 81041.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked); 81051.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored); 81061.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked); 81071.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored); 81081.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked); 81091.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored); 81101.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked); 81111.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX 81121.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX 81131.109Skamil#if TEST_VFORK_ENABLED 81141.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored); 81151.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked); 81161.109Skamil#endif 81171.103Skamil 81181.109Skamil#if TEST_VFORK_ENABLED 81191.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone); 81201.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm); 81211.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs); 81221.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files); 81231.107Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX 81241.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork); 81251.109Skamil#endif 81261.107Skamil 81271.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue); 81281.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall); 81291.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach); 81301.122Skamil 81311.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64(); 81321.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_I386(); 81331.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_X86(); 81341.1Skamil 81351.1Skamil return atf_no_error(); 81361.1Skamil} 8137