t_ptrace_wait.c revision 1.119
11.119Skamil/* $NetBSD: t_ptrace_wait.c,v 1.119 2019/05/02 00:34:06 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.119Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.119 2019/05/02 00:34:06 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.1Skamil#include <stdint.h> 501.1Skamil#include <stdio.h> 511.1Skamil#include <stdlib.h> 521.1Skamil#include <strings.h> 531.26Skamil#include <time.h> 541.1Skamil#include <unistd.h> 551.1Skamil 561.114Skamil#include <fenv.h> 571.114Skamil#if (__arm__ && !__SOFTFP__) || __aarch64__ 581.114Skamil#include <ieeefp.h> /* only need for ARM Cortex/Neon hack */ 591.114Skamil#endif 601.114Skamil 611.1Skamil#include <atf-c.h> 621.1Skamil 631.1Skamil#include "h_macros.h" 641.1Skamil 651.1Skamil#include "t_ptrace_wait.h" 661.1Skamil#include "msg.h" 671.1Skamil 681.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \ 691.61Skre SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \ 701.61Skre sizeof(msg)) == 0) 711.1Skamil 721.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \ 731.61Skre FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \ 741.61Skre sizeof(msg)) == 0) 751.1Skamil 761.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \ 771.61Skre FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \ 781.61Skre sizeof(msg)) == 0) 791.1Skamil 801.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \ 811.61Skre SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \ 821.61Skre sizeof(msg)) == 0) 831.13Schristos 841.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \ 851.13Schristos strerror(errno)) 861.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \ 871.18Schristos "%d(%s) != %d", res, strerror(res), exp) 881.13Schristos 891.13Schristosstatic int debug = 0; 901.13Schristos 911.13Schristos#define DPRINTF(a, ...) do \ 921.13Schristos if (debug) printf(a, ##__VA_ARGS__); \ 931.13Schristos while (/*CONSTCOND*/0) 941.1Skamil 951.110Skamil#ifndef TEST_VFORK_ENABLED 961.109Skamil#define TEST_VFORK_ENABLED 0 971.110Skamil#endif 981.109Skamil 991.34Skamil/// ---------------------------------------------------------------------------- 1001.34Skamil 1011.33Skamilstatic void 1021.33Skamiltraceme_raise(int sigval) 1031.1Skamil{ 1041.1Skamil const int exitval = 5; 1051.1Skamil pid_t child, wpid; 1061.1Skamil#if defined(TWAIT_HAVE_STATUS) 1071.1Skamil int status; 1081.1Skamil#endif 1091.1Skamil 1101.45Skamil struct ptrace_siginfo info; 1111.45Skamil memset(&info, 0, sizeof(info)); 1121.45Skamil 1131.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 1141.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 1151.1Skamil if (child == 0) { 1161.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1171.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1181.1Skamil 1191.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1201.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 1211.1Skamil 1221.36Skamil switch (sigval) { 1231.36Skamil case SIGKILL: 1241.36Skamil /* NOTREACHED */ 1251.36Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 1261.70Smrg __unreachable(); 1271.36Skamil default: 1281.36Skamil DPRINTF("Before exiting of the child process\n"); 1291.36Skamil _exit(exitval); 1301.36Skamil } 1311.1Skamil } 1321.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1331.1Skamil 1341.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1351.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1361.1Skamil 1371.36Skamil switch (sigval) { 1381.36Skamil case SIGKILL: 1391.36Skamil validate_status_signaled(status, sigval, 0); 1401.36Skamil break; 1411.36Skamil default: 1421.36Skamil validate_status_stopped(status, sigval); 1431.1Skamil 1441.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 1451.61Skre "child\n"); 1461.45Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 1471.61Skre sizeof(info)) != -1); 1481.45Skamil 1491.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1501.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 1511.61Skre "si_errno=%#x\n", 1521.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1531.61Skre info.psi_siginfo.si_errno); 1541.45Skamil 1551.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 1561.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 1571.45Skamil 1581.36Skamil DPRINTF("Before resuming the child process where it left off " 1591.36Skamil "and without signal to be sent\n"); 1601.36Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1611.1Skamil 1621.36Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1631.36Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 1641.61Skre child); 1651.36Skamil break; 1661.36Skamil } 1671.1Skamil 1681.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1691.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 1701.1Skamil} 1711.1Skamil 1721.61Skre#define TRACEME_RAISE(test, sig) \ 1731.61SkreATF_TC(test); \ 1741.61SkreATF_TC_HEAD(test, tc) \ 1751.61Skre{ \ 1761.61Skre atf_tc_set_md_var(tc, "descr", \ 1771.61Skre "Verify " #sig " followed by _exit(2) in a child"); \ 1781.61Skre} \ 1791.61Skre \ 1801.61SkreATF_TC_BODY(test, tc) \ 1811.61Skre{ \ 1821.61Skre \ 1831.61Skre traceme_raise(sig); \ 1841.33Skamil} 1851.33Skamil 1861.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */ 1871.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */ 1881.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */ 1891.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP) /* hangup */ 1901.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */ 1911.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */ 1921.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */ 1931.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */ 1941.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */ 1951.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */ 1961.33Skamil 1971.34Skamil/// ---------------------------------------------------------------------------- 1981.1Skamil 1991.1Skamilstatic void 2001.87Skamiltraceme_raisesignal_ignored(int sigignored) 2011.87Skamil{ 2021.87Skamil const int exitval = 5; 2031.87Skamil const int sigval = SIGSTOP; 2041.87Skamil pid_t child, wpid; 2051.87Skamil struct sigaction sa; 2061.87Skamil#if defined(TWAIT_HAVE_STATUS) 2071.87Skamil int status; 2081.87Skamil#endif 2091.87Skamil struct ptrace_siginfo info; 2101.87Skamil 2111.87Skamil memset(&info, 0, sizeof(info)); 2121.87Skamil 2131.87Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 2141.87Skamil SYSCALL_REQUIRE((child = fork()) != -1); 2151.87Skamil if (child == 0) { 2161.87Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2171.87Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2181.87Skamil 2191.87Skamil memset(&sa, 0, sizeof(sa)); 2201.87Skamil sa.sa_handler = SIG_IGN; 2211.87Skamil sigemptyset(&sa.sa_mask); 2221.87Skamil FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1); 2231.87Skamil 2241.87Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 2251.87Skamil FORKEE_ASSERT(raise(sigval) == 0); 2261.87Skamil 2271.87Skamil DPRINTF("Before raising %s from child\n", 2281.87Skamil strsignal(sigignored)); 2291.87Skamil FORKEE_ASSERT(raise(sigignored) == 0); 2301.87Skamil 2311.87Skamil DPRINTF("Before exiting of the child process\n"); 2321.87Skamil _exit(exitval); 2331.87Skamil } 2341.87Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2351.87Skamil 2361.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2371.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2381.87Skamil 2391.87Skamil validate_status_stopped(status, sigval); 2401.87Skamil 2411.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2421.87Skamil SYSCALL_REQUIRE( 2431.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2441.87Skamil 2451.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2461.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2471.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2481.87Skamil info.psi_siginfo.si_errno); 2491.87Skamil 2501.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 2511.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2521.87Skamil 2531.87Skamil DPRINTF("Before resuming the child process where it left off and " 2541.87Skamil "without signal to be sent\n"); 2551.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2561.87Skamil 2571.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2581.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2591.87Skamil 2601.87Skamil validate_status_stopped(status, sigignored); 2611.87Skamil 2621.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2631.87Skamil SYSCALL_REQUIRE( 2641.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2651.87Skamil 2661.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2671.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2681.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2691.87Skamil info.psi_siginfo.si_errno); 2701.87Skamil 2711.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored); 2721.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2731.87Skamil 2741.87Skamil DPRINTF("Before resuming the child process where it left off and " 2751.87Skamil "without signal to be sent\n"); 2761.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2771.87Skamil 2781.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2791.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2801.87Skamil 2811.87Skamil validate_status_exited(status, exitval); 2821.87Skamil 2831.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2841.87Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 2851.87Skamil} 2861.87Skamil 2871.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig) \ 2881.87SkamilATF_TC(test); \ 2891.87SkamilATF_TC_HEAD(test, tc) \ 2901.87Skamil{ \ 2911.87Skamil atf_tc_set_md_var(tc, "descr", \ 2921.87Skamil "Verify that ignoring (with SIG_IGN) " #sig " in tracee " \ 2931.87Skamil "does not stop tracer from catching this raised signal"); \ 2941.87Skamil} \ 2951.87Skamil \ 2961.87SkamilATF_TC_BODY(test, tc) \ 2971.87Skamil{ \ 2981.87Skamil \ 2991.87Skamil traceme_raisesignal_ignored(sig); \ 3001.87Skamil} 3011.87Skamil 3021.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 3031.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */ 3041.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP) /* hangup */ 3051.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */ 3061.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */ 3071.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */ 3081.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */ 3091.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */ 3101.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */ 3111.87Skamil 3121.87Skamil/// ---------------------------------------------------------------------------- 3131.87Skamil 3141.87Skamilstatic void 3151.86Skamiltraceme_raisesignal_masked(int sigmasked) 3161.86Skamil{ 3171.86Skamil const int exitval = 5; 3181.86Skamil const int sigval = SIGSTOP; 3191.86Skamil pid_t child, wpid; 3201.86Skamil#if defined(TWAIT_HAVE_STATUS) 3211.86Skamil int status; 3221.86Skamil#endif 3231.86Skamil sigset_t intmask; 3241.86Skamil struct ptrace_siginfo info; 3251.86Skamil 3261.86Skamil memset(&info, 0, sizeof(info)); 3271.86Skamil 3281.86Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 3291.86Skamil SYSCALL_REQUIRE((child = fork()) != -1); 3301.86Skamil if (child == 0) { 3311.86Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 3321.86Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 3331.86Skamil 3341.86Skamil sigemptyset(&intmask); 3351.86Skamil sigaddset(&intmask, sigmasked); 3361.86Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 3371.86Skamil 3381.86Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 3391.86Skamil FORKEE_ASSERT(raise(sigval) == 0); 3401.86Skamil 3411.86Skamil DPRINTF("Before raising %s breakpoint from child\n", 3421.86Skamil strsignal(sigmasked)); 3431.86Skamil FORKEE_ASSERT(raise(sigmasked) == 0); 3441.86Skamil 3451.86Skamil DPRINTF("Before exiting of the child process\n"); 3461.86Skamil _exit(exitval); 3471.86Skamil } 3481.86Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 3491.86Skamil 3501.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3511.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3521.86Skamil 3531.86Skamil validate_status_stopped(status, sigval); 3541.86Skamil 3551.86Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 3561.86Skamil SYSCALL_REQUIRE( 3571.86Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 3581.86Skamil 3591.86Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 3601.86Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 3611.86Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 3621.86Skamil info.psi_siginfo.si_errno); 3631.86Skamil 3641.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 3651.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 3661.86Skamil 3671.86Skamil DPRINTF("Before resuming the child process where it left off and " 3681.86Skamil "without signal to be sent\n"); 3691.86Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 3701.86Skamil 3711.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3721.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3731.86Skamil 3741.86Skamil validate_status_exited(status, exitval); 3751.86Skamil 3761.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3771.86Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 3781.86Skamil} 3791.86Skamil 3801.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig) \ 3811.86SkamilATF_TC(test); \ 3821.86SkamilATF_TC_HEAD(test, tc) \ 3831.86Skamil{ \ 3841.86Skamil atf_tc_set_md_var(tc, "descr", \ 3851.86Skamil "Verify that masking (with SIG_BLOCK) " #sig " in tracee " \ 3861.86Skamil "stops tracer from catching this raised signal"); \ 3871.86Skamil} \ 3881.86Skamil \ 3891.86SkamilATF_TC_BODY(test, tc) \ 3901.86Skamil{ \ 3911.86Skamil \ 3921.86Skamil traceme_raisesignal_masked(sig); \ 3931.86Skamil} 3941.86Skamil 3951.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 3961.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */ 3971.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP) /* hangup */ 3981.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */ 3991.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */ 4001.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */ 4011.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */ 4021.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */ 4031.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */ 4041.86Skamil 4051.86Skamil/// ---------------------------------------------------------------------------- 4061.86Skamil 4071.86Skamilstatic void 4081.59Skamiltraceme_crash(int sig) 4091.59Skamil{ 4101.59Skamil pid_t child, wpid; 4111.59Skamil#if defined(TWAIT_HAVE_STATUS) 4121.59Skamil int status; 4131.59Skamil#endif 4141.59Skamil struct ptrace_siginfo info; 4151.61Skre 4161.71Skamil#ifndef PTRACE_ILLEGAL_ASM 4171.71Skamil if (sig == SIGILL) 4181.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 4191.71Skamil#endif 4201.71Skamil 4211.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 4221.114Skamil atf_tc_skip("FP exceptions are not supported"); 4231.114Skamil 4241.59Skamil memset(&info, 0, sizeof(info)); 4251.59Skamil 4261.59Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 4271.59Skamil SYSCALL_REQUIRE((child = fork()) != -1); 4281.59Skamil if (child == 0) { 4291.59Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 4301.59Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 4311.59Skamil 4321.59Skamil DPRINTF("Before executing a trap\n"); 4331.59Skamil switch (sig) { 4341.59Skamil case SIGTRAP: 4351.59Skamil trigger_trap(); 4361.59Skamil break; 4371.59Skamil case SIGSEGV: 4381.59Skamil trigger_segv(); 4391.59Skamil break; 4401.59Skamil case SIGILL: 4411.59Skamil trigger_ill(); 4421.59Skamil break; 4431.59Skamil case SIGFPE: 4441.59Skamil trigger_fpe(); 4451.59Skamil break; 4461.59Skamil case SIGBUS: 4471.59Skamil trigger_bus(); 4481.59Skamil break; 4491.59Skamil default: 4501.59Skamil /* NOTREACHED */ 4511.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4521.59Skamil } 4531.59Skamil 4541.59Skamil /* NOTREACHED */ 4551.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4561.59Skamil } 4571.59Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 4581.59Skamil 4591.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4601.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4611.59Skamil 4621.59Skamil validate_status_stopped(status, sig); 4631.59Skamil 4641.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 4651.61Skre SYSCALL_REQUIRE( 4661.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 4671.59Skamil 4681.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 4691.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 4701.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 4711.61Skre info.psi_siginfo.si_errno); 4721.59Skamil 4731.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 4741.59Skamil switch (sig) { 4751.59Skamil case SIGTRAP: 4761.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 4771.59Skamil break; 4781.59Skamil case SIGSEGV: 4791.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 4801.59Skamil break; 4811.71Skamil case SIGILL: 4821.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 4831.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 4841.71Skamil break; 4851.59Skamil case SIGFPE: 4861.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 4871.59Skamil break; 4881.59Skamil case SIGBUS: 4891.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 4901.59Skamil break; 4911.59Skamil } 4921.59Skamil 4931.59Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 4941.59Skamil 4951.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4961.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4971.59Skamil 4981.59Skamil validate_status_signaled(status, SIGKILL, 0); 4991.59Skamil 5001.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5011.59Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 5021.59Skamil} 5031.59Skamil 5041.61Skre#define TRACEME_CRASH(test, sig) \ 5051.61SkreATF_TC(test); \ 5061.61SkreATF_TC_HEAD(test, tc) \ 5071.61Skre{ \ 5081.61Skre atf_tc_set_md_var(tc, "descr", \ 5091.61Skre "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \ 5101.61Skre} \ 5111.61Skre \ 5121.61SkreATF_TC_BODY(test, tc) \ 5131.61Skre{ \ 5141.61Skre \ 5151.61Skre traceme_crash(sig); \ 5161.59Skamil} 5171.59Skamil 5181.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP) 5191.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV) 5201.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL) 5211.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE) 5221.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS) 5231.59Skamil 5241.59Skamil/// ---------------------------------------------------------------------------- 5251.59Skamil 5261.59Skamilstatic void 5271.88Skamiltraceme_signalmasked_crash(int sig) 5281.88Skamil{ 5291.89Skamil const int sigval = SIGSTOP; 5301.88Skamil pid_t child, wpid; 5311.88Skamil#if defined(TWAIT_HAVE_STATUS) 5321.88Skamil int status; 5331.88Skamil#endif 5341.88Skamil struct ptrace_siginfo info; 5351.88Skamil sigset_t intmask; 5361.89Skamil struct kinfo_proc2 kp; 5371.89Skamil size_t len = sizeof(kp); 5381.89Skamil 5391.89Skamil int name[6]; 5401.89Skamil const size_t namelen = __arraycount(name); 5411.89Skamil ki_sigset_t kp_sigmask; 5421.88Skamil 5431.88Skamil#ifndef PTRACE_ILLEGAL_ASM 5441.88Skamil if (sig == SIGILL) 5451.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 5461.88Skamil#endif 5471.88Skamil 5481.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 5491.114Skamil atf_tc_skip("FP exceptions are not supported"); 5501.114Skamil 5511.88Skamil memset(&info, 0, sizeof(info)); 5521.88Skamil 5531.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 5541.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 5551.88Skamil if (child == 0) { 5561.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 5571.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 5581.88Skamil 5591.88Skamil sigemptyset(&intmask); 5601.88Skamil sigaddset(&intmask, sig); 5611.88Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 5621.88Skamil 5631.89Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 5641.89Skamil FORKEE_ASSERT(raise(sigval) == 0); 5651.89Skamil 5661.88Skamil DPRINTF("Before executing a trap\n"); 5671.88Skamil switch (sig) { 5681.88Skamil case SIGTRAP: 5691.88Skamil trigger_trap(); 5701.88Skamil break; 5711.88Skamil case SIGSEGV: 5721.88Skamil trigger_segv(); 5731.88Skamil break; 5741.88Skamil case SIGILL: 5751.88Skamil trigger_ill(); 5761.88Skamil break; 5771.88Skamil case SIGFPE: 5781.88Skamil trigger_fpe(); 5791.88Skamil break; 5801.88Skamil case SIGBUS: 5811.88Skamil trigger_bus(); 5821.88Skamil break; 5831.88Skamil default: 5841.88Skamil /* NOTREACHED */ 5851.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 5861.88Skamil } 5871.88Skamil 5881.88Skamil /* NOTREACHED */ 5891.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 5901.88Skamil } 5911.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 5921.88Skamil 5931.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5941.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 5951.88Skamil 5961.89Skamil validate_status_stopped(status, sigval); 5971.89Skamil 5981.89Skamil name[0] = CTL_KERN, 5991.89Skamil name[1] = KERN_PROC2, 6001.89Skamil name[2] = KERN_PROC_PID; 6011.89Skamil name[3] = child; 6021.89Skamil name[4] = sizeof(kp); 6031.89Skamil name[5] = 1; 6041.89Skamil 6051.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6061.89Skamil 6071.89Skamil kp_sigmask = kp.p_sigmask; 6081.89Skamil 6091.89Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 6101.89Skamil SYSCALL_REQUIRE( 6111.89Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6121.89Skamil 6131.89Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6141.89Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6151.89Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6161.89Skamil info.psi_siginfo.si_errno); 6171.89Skamil 6181.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 6191.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 6201.89Skamil 6211.89Skamil DPRINTF("Before resuming the child process where it left off and " 6221.89Skamil "without signal to be sent\n"); 6231.89Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 6241.89Skamil 6251.89Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6261.89Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6271.89Skamil 6281.88Skamil validate_status_stopped(status, sig); 6291.88Skamil 6301.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 6311.88Skamil SYSCALL_REQUIRE( 6321.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6331.88Skamil 6341.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6351.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6361.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6371.88Skamil info.psi_siginfo.si_errno); 6381.88Skamil 6391.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6401.89Skamil 6411.89Skamil DPRINTF("kp_sigmask=" 6421.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6431.89Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2], 6441.89Skamil kp_sigmask.__bits[3]); 6451.89Skamil 6461.89Skamil DPRINTF("kp.p_sigmask=" 6471.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6481.89Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 6491.89Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 6501.89Skamil 6511.89Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask))); 6521.89Skamil 6531.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 6541.88Skamil switch (sig) { 6551.88Skamil case SIGTRAP: 6561.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 6571.88Skamil break; 6581.88Skamil case SIGSEGV: 6591.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 6601.88Skamil break; 6611.88Skamil case SIGILL: 6621.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 6631.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 6641.88Skamil break; 6651.88Skamil case SIGFPE: 6661.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 6671.88Skamil break; 6681.88Skamil case SIGBUS: 6691.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 6701.88Skamil break; 6711.88Skamil } 6721.88Skamil 6731.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 6741.88Skamil 6751.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6761.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6771.88Skamil 6781.88Skamil validate_status_signaled(status, SIGKILL, 0); 6791.88Skamil 6801.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6811.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 6821.88Skamil} 6831.88Skamil 6841.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig) \ 6851.88SkamilATF_TC(test); \ 6861.88SkamilATF_TC_HEAD(test, tc) \ 6871.88Skamil{ \ 6881.88Skamil atf_tc_set_md_var(tc, "descr", \ 6891.88Skamil "Verify masked crash signal " #sig " in a child after " \ 6901.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 6911.88Skamil} \ 6921.88Skamil \ 6931.88SkamilATF_TC_BODY(test, tc) \ 6941.88Skamil{ \ 6951.88Skamil \ 6961.88Skamil traceme_signalmasked_crash(sig); \ 6971.88Skamil} 6981.88Skamil 6991.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP) 7001.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV) 7011.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL) 7021.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE) 7031.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS) 7041.88Skamil 7051.88Skamil/// ---------------------------------------------------------------------------- 7061.88Skamil 7071.88Skamilstatic void 7081.88Skamiltraceme_signalignored_crash(int sig) 7091.88Skamil{ 7101.90Skamil const int sigval = SIGSTOP; 7111.88Skamil pid_t child, wpid; 7121.88Skamil#if defined(TWAIT_HAVE_STATUS) 7131.88Skamil int status; 7141.88Skamil#endif 7151.88Skamil struct sigaction sa; 7161.88Skamil struct ptrace_siginfo info; 7171.90Skamil struct kinfo_proc2 kp; 7181.90Skamil size_t len = sizeof(kp); 7191.90Skamil 7201.90Skamil int name[6]; 7211.90Skamil const size_t namelen = __arraycount(name); 7221.90Skamil ki_sigset_t kp_sigignore; 7231.88Skamil 7241.88Skamil#ifndef PTRACE_ILLEGAL_ASM 7251.88Skamil if (sig == SIGILL) 7261.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 7271.88Skamil#endif 7281.88Skamil 7291.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 7301.114Skamil atf_tc_skip("FP exceptions are not supported"); 7311.114Skamil 7321.88Skamil memset(&info, 0, sizeof(info)); 7331.88Skamil 7341.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 7351.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 7361.88Skamil if (child == 0) { 7371.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 7381.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 7391.88Skamil 7401.88Skamil memset(&sa, 0, sizeof(sa)); 7411.88Skamil sa.sa_handler = SIG_IGN; 7421.88Skamil sigemptyset(&sa.sa_mask); 7431.88Skamil 7441.88Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 7451.88Skamil 7461.90Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 7471.90Skamil FORKEE_ASSERT(raise(sigval) == 0); 7481.90Skamil 7491.88Skamil DPRINTF("Before executing a trap\n"); 7501.88Skamil switch (sig) { 7511.88Skamil case SIGTRAP: 7521.88Skamil trigger_trap(); 7531.88Skamil break; 7541.88Skamil case SIGSEGV: 7551.88Skamil trigger_segv(); 7561.88Skamil break; 7571.88Skamil case SIGILL: 7581.88Skamil trigger_ill(); 7591.88Skamil break; 7601.88Skamil case SIGFPE: 7611.88Skamil trigger_fpe(); 7621.88Skamil break; 7631.88Skamil case SIGBUS: 7641.88Skamil trigger_bus(); 7651.88Skamil break; 7661.88Skamil default: 7671.88Skamil /* NOTREACHED */ 7681.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7691.88Skamil } 7701.88Skamil 7711.88Skamil /* NOTREACHED */ 7721.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7731.88Skamil } 7741.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 7751.88Skamil 7761.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7771.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 7781.88Skamil 7791.90Skamil validate_status_stopped(status, sigval); 7801.90Skamil 7811.90Skamil name[0] = CTL_KERN, 7821.90Skamil name[1] = KERN_PROC2, 7831.90Skamil name[2] = KERN_PROC_PID; 7841.90Skamil name[3] = child; 7851.90Skamil name[4] = sizeof(kp); 7861.90Skamil name[5] = 1; 7871.90Skamil 7881.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 7891.90Skamil 7901.90Skamil kp_sigignore = kp.p_sigignore; 7911.90Skamil 7921.90Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 7931.90Skamil SYSCALL_REQUIRE( 7941.90Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 7951.90Skamil 7961.90Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 7971.90Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 7981.90Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 7991.90Skamil info.psi_siginfo.si_errno); 8001.90Skamil 8011.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 8021.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 8031.90Skamil 8041.90Skamil DPRINTF("Before resuming the child process where it left off and " 8051.90Skamil "without signal to be sent\n"); 8061.90Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 8071.90Skamil 8081.90Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8091.90Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8101.90Skamil 8111.88Skamil validate_status_stopped(status, sig); 8121.88Skamil 8131.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 8141.88Skamil SYSCALL_REQUIRE( 8151.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8161.88Skamil 8171.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8181.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8191.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8201.88Skamil info.psi_siginfo.si_errno); 8211.88Skamil 8221.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8231.90Skamil 8241.90Skamil DPRINTF("kp_sigignore=" 8251.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8261.90Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 8271.90Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 8281.90Skamil 8291.90Skamil DPRINTF("kp.p_sigignore=" 8301.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8311.90Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 8321.90Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 8331.90Skamil 8341.90Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore))); 8351.90Skamil 8361.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 8371.88Skamil switch (sig) { 8381.88Skamil case SIGTRAP: 8391.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 8401.88Skamil break; 8411.88Skamil case SIGSEGV: 8421.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 8431.88Skamil break; 8441.88Skamil case SIGILL: 8451.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 8461.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 8471.88Skamil break; 8481.88Skamil case SIGFPE: 8491.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 8501.88Skamil break; 8511.88Skamil case SIGBUS: 8521.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 8531.88Skamil break; 8541.88Skamil } 8551.88Skamil 8561.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 8571.88Skamil 8581.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8591.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8601.88Skamil 8611.88Skamil validate_status_signaled(status, SIGKILL, 0); 8621.88Skamil 8631.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8641.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 8651.88Skamil} 8661.88Skamil 8671.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig) \ 8681.88SkamilATF_TC(test); \ 8691.88SkamilATF_TC_HEAD(test, tc) \ 8701.88Skamil{ \ 8711.88Skamil atf_tc_set_md_var(tc, "descr", \ 8721.88Skamil "Verify ignored crash signal " #sig " in a child after " \ 8731.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 8741.88Skamil} \ 8751.88Skamil \ 8761.88SkamilATF_TC_BODY(test, tc) \ 8771.88Skamil{ \ 8781.88Skamil \ 8791.88Skamil traceme_signalignored_crash(sig); \ 8801.88Skamil} 8811.88Skamil 8821.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP) 8831.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV) 8841.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL) 8851.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE) 8861.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS) 8871.88Skamil 8881.88Skamil/// ---------------------------------------------------------------------------- 8891.88Skamil 8901.88Skamilstatic void 8911.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught) 8921.1Skamil{ 8931.1Skamil const int exitval = 5; 8941.34Skamil const int sigval = SIGSTOP; 8951.1Skamil pid_t child, wpid; 8961.1Skamil struct sigaction sa; 8971.1Skamil#if defined(TWAIT_HAVE_STATUS) 8981.1Skamil int status; 8991.1Skamil#endif 9001.61Skre struct ptrace_siginfo info; 9011.1Skamil 9021.45Skamil memset(&info, 0, sizeof(info)); 9031.45Skamil 9041.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 9051.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 9061.1Skamil if (child == 0) { 9071.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 9081.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 9091.1Skamil 9101.34Skamil sa.sa_handler = sah; 9111.1Skamil sa.sa_flags = SA_SIGINFO; 9121.1Skamil sigemptyset(&sa.sa_mask); 9131.1Skamil 9141.1Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 9151.1Skamil 9161.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 9171.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 9181.1Skamil 9191.34Skamil FORKEE_ASSERT_EQ(*traceme_caught, 1); 9201.1Skamil 9211.13Schristos DPRINTF("Before exiting of the child process\n"); 9221.1Skamil _exit(exitval); 9231.1Skamil } 9241.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 9251.1Skamil 9261.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9271.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9281.1Skamil 9291.1Skamil validate_status_stopped(status, sigval); 9301.1Skamil 9311.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 9321.61Skre SYSCALL_REQUIRE( 9331.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 9341.45Skamil 9351.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 9361.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 9371.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 9381.45Skamil info.psi_siginfo.si_errno); 9391.45Skamil 9401.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 9411.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 9421.45Skamil 9431.13Schristos DPRINTF("Before resuming the child process where it left off and with " 9441.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 9451.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 9461.1Skamil 9471.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9481.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9491.1Skamil 9501.1Skamil validate_status_exited(status, exitval); 9511.1Skamil 9521.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 9531.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 9541.1Skamil} 9551.1Skamil 9561.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig) \ 9571.61SkreATF_TC(test); \ 9581.61SkreATF_TC_HEAD(test, tc) \ 9591.61Skre{ \ 9601.61Skre atf_tc_set_md_var(tc, "descr", \ 9611.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 9621.61Skre "handled correctly and caught by a signal handler"); \ 9631.61Skre} \ 9641.61Skre \ 9651.61Skrestatic int test##_caught = 0; \ 9661.61Skre \ 9671.61Skrestatic void \ 9681.61Skretest##_sighandler(int arg) \ 9691.61Skre{ \ 9701.61Skre FORKEE_ASSERT_EQ(arg, sig); \ 9711.61Skre \ 9721.61Skre ++ test##_caught; \ 9731.61Skre} \ 9741.61Skre \ 9751.61SkreATF_TC_BODY(test, tc) \ 9761.61Skre{ \ 9771.61Skre \ 9781.61Skre traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \ 9791.34Skamil} 9801.34Skamil 9811.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered. 9821.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */ 9831.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP) /* hangup */ 9841.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */ 9851.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */ 9861.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */ 9871.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */ 9881.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */ 9891.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */ 9901.34Skamil 9911.34Skamil/// ---------------------------------------------------------------------------- 9921.34Skamil 9931.35Skamilstatic void 9941.50Skamiltraceme_sendsignal_masked(int sigsent) 9951.50Skamil{ 9961.50Skamil const int exitval = 5; 9971.50Skamil const int sigval = SIGSTOP; 9981.50Skamil pid_t child, wpid; 9991.50Skamil sigset_t set; 10001.50Skamil#if defined(TWAIT_HAVE_STATUS) 10011.50Skamil int status; 10021.50Skamil#endif 10031.61Skre struct ptrace_siginfo info; 10041.50Skamil 10051.50Skamil memset(&info, 0, sizeof(info)); 10061.50Skamil 10071.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 10081.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 10091.50Skamil if (child == 0) { 10101.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 10111.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 10121.50Skamil 10131.50Skamil sigemptyset(&set); 10141.50Skamil sigaddset(&set, sigsent); 10151.50Skamil FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 10161.50Skamil 10171.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 10181.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 10191.50Skamil 10201.50Skamil _exit(exitval); 10211.50Skamil } 10221.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 10231.50Skamil 10241.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10251.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10261.50Skamil 10271.50Skamil validate_status_stopped(status, sigval); 10281.50Skamil 10291.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 10301.61Skre SYSCALL_REQUIRE( 10311.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 10321.50Skamil 10331.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 10341.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 10351.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 10361.50Skamil info.psi_siginfo.si_errno); 10371.50Skamil 10381.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 10391.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 10401.50Skamil 10411.50Skamil DPRINTF("Before resuming the child process where it left off and with " 10421.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 10431.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 10441.50Skamil 10451.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10461.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10471.50Skamil 10481.50Skamil validate_status_exited(status, exitval); 10491.50Skamil 10501.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 10511.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 10521.50Skamil} 10531.50Skamil 10541.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig) \ 10551.61SkreATF_TC(test); \ 10561.61SkreATF_TC_HEAD(test, tc) \ 10571.61Skre{ \ 10581.61Skre atf_tc_set_md_var(tc, "descr", \ 10591.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 10601.61Skre "handled correctly and the signal is masked by SIG_BLOCK"); \ 10611.61Skre} \ 10621.61Skre \ 10631.61SkreATF_TC_BODY(test, tc) \ 10641.61Skre{ \ 10651.61Skre \ 10661.61Skre traceme_sendsignal_masked(sig); \ 10671.50Skamil} 10681.50Skamil 10691.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 10701.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */ 10711.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP) /* hangup */ 10721.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */ 10731.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */ 10741.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */ 10751.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */ 10761.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */ 10771.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */ 10781.50Skamil 10791.50Skamil/// ---------------------------------------------------------------------------- 10801.50Skamil 10811.50Skamilstatic void 10821.50Skamiltraceme_sendsignal_ignored(int sigsent) 10831.50Skamil{ 10841.50Skamil const int exitval = 5; 10851.50Skamil const int sigval = SIGSTOP; 10861.50Skamil pid_t child, wpid; 10871.50Skamil struct sigaction sa; 10881.50Skamil#if defined(TWAIT_HAVE_STATUS) 10891.50Skamil int status; 10901.50Skamil#endif 10911.61Skre struct ptrace_siginfo info; 10921.50Skamil 10931.50Skamil memset(&info, 0, sizeof(info)); 10941.50Skamil 10951.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 10961.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 10971.50Skamil if (child == 0) { 10981.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 10991.61Skre 11001.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 11011.50Skamil 11021.50Skamil memset(&sa, 0, sizeof(sa)); 11031.50Skamil sa.sa_handler = SIG_IGN; 11041.50Skamil sigemptyset(&sa.sa_mask); 11051.50Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 11061.50Skamil 11071.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 11081.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 11091.50Skamil 11101.50Skamil _exit(exitval); 11111.50Skamil } 11121.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 11131.50Skamil 11141.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11151.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11161.50Skamil 11171.50Skamil validate_status_stopped(status, sigval); 11181.50Skamil 11191.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 11201.61Skre SYSCALL_REQUIRE( 11211.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 11221.50Skamil 11231.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 11241.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 11251.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 11261.50Skamil info.psi_siginfo.si_errno); 11271.50Skamil 11281.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 11291.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 11301.50Skamil 11311.50Skamil DPRINTF("Before resuming the child process where it left off and with " 11321.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 11331.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 11341.50Skamil 11351.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11361.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11371.50Skamil 11381.50Skamil validate_status_exited(status, exitval); 11391.50Skamil 11401.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 11411.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 11421.50Skamil} 11431.50Skamil 11441.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig) \ 11451.61SkreATF_TC(test); \ 11461.61SkreATF_TC_HEAD(test, tc) \ 11471.61Skre{ \ 11481.61Skre atf_tc_set_md_var(tc, "descr", \ 11491.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 11501.61Skre "handled correctly and the signal is masked by SIG_IGN"); \ 11511.61Skre} \ 11521.61Skre \ 11531.61SkreATF_TC_BODY(test, tc) \ 11541.61Skre{ \ 11551.61Skre \ 11561.61Skre traceme_sendsignal_ignored(sig); \ 11571.50Skamil} 11581.50Skamil 11591.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 11601.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */ 11611.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP) /* hangup */ 11621.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */ 11631.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */ 11641.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */ 11651.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */ 11661.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */ 11671.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */ 11681.50Skamil 11691.50Skamil/// ---------------------------------------------------------------------------- 11701.50Skamil 11711.50Skamilstatic void 11721.50Skamiltraceme_sendsignal_simple(int sigsent) 11731.1Skamil{ 11741.35Skamil const int sigval = SIGSTOP; 11751.35Skamil int exitval = 0; 11761.1Skamil pid_t child, wpid; 11771.1Skamil#if defined(TWAIT_HAVE_STATUS) 11781.1Skamil int status; 11791.85Skamil int expect_core; 11801.85Skamil 11811.85Skamil switch (sigsent) { 11821.85Skamil case SIGABRT: 11831.85Skamil case SIGTRAP: 11841.85Skamil case SIGBUS: 11851.85Skamil case SIGILL: 11861.85Skamil case SIGFPE: 11871.85Skamil case SIGSEGV: 11881.85Skamil expect_core = 1; 11891.85Skamil break; 11901.85Skamil default: 11911.85Skamil expect_core = 0; 11921.85Skamil break; 11931.85Skamil } 11941.1Skamil#endif 11951.61Skre struct ptrace_siginfo info; 11961.1Skamil 11971.45Skamil memset(&info, 0, sizeof(info)); 11981.45Skamil 11991.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 12001.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 12011.1Skamil if (child == 0) { 12021.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 12031.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 12041.1Skamil 12051.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 12061.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 12071.1Skamil 12081.35Skamil switch (sigsent) { 12091.35Skamil case SIGCONT: 12101.48Skamil case SIGSTOP: 12111.35Skamil _exit(exitval); 12121.35Skamil default: 12131.35Skamil /* NOTREACHED */ 12141.35Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 12151.35Skamil } 12161.1Skamil } 12171.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 12181.1Skamil 12191.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12201.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12211.1Skamil 12221.1Skamil validate_status_stopped(status, sigval); 12231.1Skamil 12241.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 12251.61Skre SYSCALL_REQUIRE( 12261.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 12271.45Skamil 12281.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12291.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 12301.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12311.45Skamil info.psi_siginfo.si_errno); 12321.45Skamil 12331.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12341.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12351.45Skamil 12361.13Schristos DPRINTF("Before resuming the child process where it left off and with " 12371.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 12381.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 12391.1Skamil 12401.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12411.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12421.1Skamil 12431.35Skamil switch (sigsent) { 12441.48Skamil case SIGSTOP: 12451.48Skamil validate_status_stopped(status, sigsent); 12461.48Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 12471.61Skre "child\n"); 12481.48Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 12491.61Skre sizeof(info)) != -1); 12501.48Skamil 12511.48Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12521.48Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 12531.61Skre "si_errno=%#x\n", 12541.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12551.61Skre info.psi_siginfo.si_errno); 12561.48Skamil 12571.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12581.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12591.48Skamil 12601.48Skamil DPRINTF("Before resuming the child process where it left off " 12611.61Skre "and with signal %s to be sent\n", strsignal(sigsent)); 12621.48Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 12631.48Skamil 12641.48Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12651.48Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 12661.61Skre child); 12671.48Skamil /* FALLTHROUGH */ 12681.35Skamil case SIGCONT: 12691.35Skamil validate_status_exited(status, exitval); 12701.35Skamil break; 12711.35Skamil default: 12721.35Skamil validate_status_signaled(status, sigsent, expect_core); 12731.35Skamil break; 12741.35Skamil } 12751.1Skamil 12761.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 12771.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 12781.1Skamil} 12791.1Skamil 12801.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig) \ 12811.61SkreATF_TC(test); \ 12821.61SkreATF_TC_HEAD(test, tc) \ 12831.61Skre{ \ 12841.61Skre atf_tc_set_md_var(tc, "descr", \ 12851.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 12861.61Skre "handled correctly in a child without a signal handler"); \ 12871.61Skre} \ 12881.61Skre \ 12891.61SkreATF_TC_BODY(test, tc) \ 12901.61Skre{ \ 12911.61Skre \ 12921.61Skre traceme_sendsignal_simple(sig); \ 12931.35Skamil} 12941.35Skamil 12951.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/ 12961.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/ 12971.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */ 12981.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP) /* hangup */ 12991.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */ 13001.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */ 13011.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */ 13021.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */ 13031.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */ 13041.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */ 13051.35Skamil 13061.35Skamil/// ---------------------------------------------------------------------------- 13071.35Skamil 13081.37SkamilATF_TC(traceme_pid1_parent); 13091.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc) 13101.37Skamil{ 13111.37Skamil atf_tc_set_md_var(tc, "descr", 13121.37Skamil "Verify that PT_TRACE_ME is not allowed when our parent is PID1"); 13131.37Skamil} 13141.37Skamil 13151.37SkamilATF_TC_BODY(traceme_pid1_parent, tc) 13161.37Skamil{ 13171.37Skamil struct msg_fds parent_child; 13181.37Skamil int exitval_child1 = 1, exitval_child2 = 2; 13191.37Skamil pid_t child1, child2, wpid; 13201.37Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 13211.37Skamil#if defined(TWAIT_HAVE_STATUS) 13221.37Skamil int status; 13231.37Skamil#endif 13241.37Skamil 13251.37Skamil SYSCALL_REQUIRE(msg_open(&parent_child) == 0); 13261.37Skamil 13271.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13281.37Skamil SYSCALL_REQUIRE((child1 = fork()) != -1); 13291.37Skamil if (child1 == 0) { 13301.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13311.37Skamil SYSCALL_REQUIRE((child2 = fork()) != -1); 13321.37Skamil if (child2 != 0) { 13331.37Skamil DPRINTF("Parent process PID=%d, child2's PID=%d\n", 13341.61Skre getpid(), child2); 13351.37Skamil _exit(exitval_child1); 13361.37Skamil } 13371.37Skamil CHILD_FROM_PARENT("exit child1", parent_child, msg); 13381.37Skamil 13391.37Skamil DPRINTF("Assert that our parent is PID1 (initproc)\n"); 13401.37Skamil FORKEE_ASSERT_EQ(getppid(), 1); 13411.37Skamil 13421.37Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 13431.37Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1); 13441.37Skamil SYSCALL_REQUIRE_ERRNO(errno, EPERM); 13451.37Skamil 13461.37Skamil CHILD_TO_PARENT("child2 exiting", parent_child, msg); 13471.37Skamil 13481.37Skamil _exit(exitval_child2); 13491.37Skamil } 13501.37Skamil DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1); 13511.37Skamil 13521.37Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 13531.61Skre TWAIT_REQUIRE_SUCCESS( 13541.61Skre wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1); 13551.37Skamil 13561.37Skamil validate_status_exited(status, exitval_child1); 13571.37Skamil 13581.37Skamil DPRINTF("Notify that child1 is dead\n"); 13591.37Skamil PARENT_TO_CHILD("exit child1", parent_child, msg); 13601.37Skamil 13611.37Skamil DPRINTF("Wait for exiting of child2\n"); 13621.37Skamil PARENT_FROM_CHILD("child2 exiting", parent_child, msg); 13631.37Skamil} 13641.37Skamil 13651.37Skamil/// ---------------------------------------------------------------------------- 13661.37Skamil 13671.40Skamilstatic void 13681.40Skamiltraceme_vfork_raise(int sigval) 13691.40Skamil{ 13701.46Skamil const int exitval = 5, exitval_watcher = 10; 13711.46Skamil pid_t child, parent, watcher, wpid; 13721.46Skamil int rv; 13731.40Skamil#if defined(TWAIT_HAVE_STATUS) 13741.40Skamil int status; 13751.85Skamil 13761.85Skamil /* volatile workarounds GCC -Werror=clobbered */ 13771.85Skamil volatile int expect_core; 13781.85Skamil 13791.85Skamil switch (sigval) { 13801.85Skamil case SIGABRT: 13811.85Skamil case SIGTRAP: 13821.85Skamil case SIGBUS: 13831.85Skamil case SIGILL: 13841.85Skamil case SIGFPE: 13851.85Skamil case SIGSEGV: 13861.85Skamil expect_core = 1; 13871.85Skamil break; 13881.85Skamil default: 13891.85Skamil expect_core = 0; 13901.85Skamil break; 13911.85Skamil } 13921.40Skamil#endif 13931.40Skamil 13941.46Skamil /* 13951.46Skamil * Spawn a dedicated thread to watch for a stopped child and emit 13961.46Skamil * the SIGKILL signal to it. 13971.46Skamil * 13981.46Skamil * vfork(2) might clobber watcher, this means that it's safer and 13991.46Skamil * simpler to reparent this process to initproc and forget about it. 14001.46Skamil */ 14011.46Skamil if (sigval == SIGSTOP) { 14021.46Skamil parent = getpid(); 14031.46Skamil 14041.46Skamil watcher = fork(); 14051.46Skamil ATF_REQUIRE(watcher != 1); 14061.46Skamil if (watcher == 0) { 14071.46Skamil /* Double fork(2) trick to reparent to initproc */ 14081.46Skamil watcher = fork(); 14091.46Skamil FORKEE_ASSERT_NEQ(watcher, -1); 14101.46Skamil if (watcher != 0) 14111.46Skamil _exit(exitval_watcher); 14121.46Skamil 14131.46Skamil child = await_stopped_child(parent); 14141.46Skamil 14151.46Skamil errno = 0; 14161.46Skamil rv = kill(child, SIGKILL); 14171.46Skamil FORKEE_ASSERT_EQ(rv, 0); 14181.46Skamil FORKEE_ASSERT_EQ(errno, 0); 14191.46Skamil 14201.46Skamil /* This exit value will be collected by initproc */ 14211.46Skamil _exit(0); 14221.46Skamil } 14231.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14241.46Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0), 14251.61Skre watcher); 14261.46Skamil 14271.46Skamil validate_status_exited(status, exitval_watcher); 14281.46Skamil 14291.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14301.61Skre TWAIT_REQUIRE_FAILURE(ECHILD, 14311.61Skre wpid = TWAIT_GENERIC(watcher, &status, 0)); 14321.46Skamil } 14331.46Skamil 14341.40Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 14351.40Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 14361.40Skamil if (child == 0) { 14371.40Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 14381.40Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 14391.40Skamil 14401.40Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 14411.40Skamil FORKEE_ASSERT(raise(sigval) == 0); 14421.40Skamil 14431.40Skamil switch (sigval) { 14441.46Skamil case SIGSTOP: 14451.40Skamil case SIGKILL: 14461.40Skamil case SIGABRT: 14471.40Skamil case SIGHUP: 14481.85Skamil case SIGTRAP: 14491.85Skamil case SIGBUS: 14501.85Skamil case SIGILL: 14511.85Skamil case SIGFPE: 14521.85Skamil case SIGSEGV: 14531.40Skamil /* NOTREACHED */ 14541.40Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 14551.70Smrg __unreachable(); 14561.40Skamil default: 14571.40Skamil DPRINTF("Before exiting of the child process\n"); 14581.40Skamil _exit(exitval); 14591.40Skamil } 14601.40Skamil } 14611.40Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 14621.40Skamil 14631.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14641.40Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 14651.40Skamil 14661.40Skamil switch (sigval) { 14671.40Skamil case SIGKILL: 14681.40Skamil case SIGABRT: 14691.40Skamil case SIGHUP: 14701.85Skamil case SIGTRAP: 14711.85Skamil case SIGBUS: 14721.85Skamil case SIGILL: 14731.85Skamil case SIGFPE: 14741.85Skamil case SIGSEGV: 14751.40Skamil validate_status_signaled(status, sigval, expect_core); 14761.40Skamil break; 14771.40Skamil case SIGSTOP: 14781.46Skamil validate_status_signaled(status, SIGKILL, 0); 14791.46Skamil break; 14801.40Skamil case SIGCONT: 14811.47Skamil case SIGTSTP: 14821.47Skamil case SIGTTIN: 14831.47Skamil case SIGTTOU: 14841.40Skamil validate_status_exited(status, exitval); 14851.40Skamil break; 14861.40Skamil default: 14871.40Skamil /* NOTREACHED */ 14881.40Skamil ATF_REQUIRE(0 && "NOT IMPLEMENTED"); 14891.40Skamil break; 14901.40Skamil } 14911.40Skamil 14921.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14931.40Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 14941.40Skamil} 14951.40Skamil 14961.61Skre#define TRACEME_VFORK_RAISE(test, sig) \ 14971.61SkreATF_TC(test); \ 14981.61SkreATF_TC_HEAD(test, tc) \ 14991.61Skre{ \ 15001.61Skre atf_tc_set_md_var(tc, "descr", \ 15011.61Skre "Verify PT_TRACE_ME followed by raise of " #sig " in a " \ 15021.61Skre "vfork(2)ed child"); \ 15031.61Skre} \ 15041.61Skre \ 15051.61SkreATF_TC_BODY(test, tc) \ 15061.61Skre{ \ 15071.61Skre \ 15081.61Skre traceme_vfork_raise(sig); \ 15091.40Skamil} 15101.40Skamil 15111.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */ 15121.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */ 15131.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */ 15141.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */ 15151.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */ 15161.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */ 15171.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP) /* hangup */ 15181.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */ 15191.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */ 15201.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */ 15211.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */ 15221.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */ 15231.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */ 15241.40Skamil 15251.40Skamil/// ---------------------------------------------------------------------------- 15261.40Skamil 15271.52Skamilstatic void 15281.52Skamiltraceme_vfork_crash(int sig) 15291.41Skamil{ 15301.41Skamil pid_t child, wpid; 15311.41Skamil#if defined(TWAIT_HAVE_STATUS) 15321.41Skamil int status; 15331.41Skamil#endif 15341.41Skamil 15351.71Skamil#ifndef PTRACE_ILLEGAL_ASM 15361.71Skamil if (sig == SIGILL) 15371.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 15381.71Skamil#endif 15391.71Skamil 15401.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 15411.114Skamil atf_tc_skip("FP exceptions are not supported"); 15421.114Skamil 15431.41Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 15441.41Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 15451.41Skamil if (child == 0) { 15461.41Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 15471.41Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 15481.41Skamil 15491.52Skamil DPRINTF("Before executing a trap\n"); 15501.52Skamil switch (sig) { 15511.52Skamil case SIGTRAP: 15521.52Skamil trigger_trap(); 15531.52Skamil break; 15541.52Skamil case SIGSEGV: 15551.52Skamil trigger_segv(); 15561.52Skamil break; 15571.52Skamil case SIGILL: 15581.52Skamil trigger_ill(); 15591.52Skamil break; 15601.52Skamil case SIGFPE: 15611.52Skamil trigger_fpe(); 15621.52Skamil break; 15631.52Skamil case SIGBUS: 15641.52Skamil trigger_bus(); 15651.52Skamil break; 15661.52Skamil default: 15671.52Skamil /* NOTREACHED */ 15681.52Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15691.52Skamil } 15701.41Skamil 15711.41Skamil /* NOTREACHED */ 15721.41Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15731.41Skamil } 15741.41Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 15751.41Skamil 15761.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15771.41Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 15781.41Skamil 15791.52Skamil validate_status_signaled(status, sig, 1); 15801.41Skamil 15811.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15821.41Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15831.41Skamil} 15841.41Skamil 15851.61Skre#define TRACEME_VFORK_CRASH(test, sig) \ 15861.61SkreATF_TC(test); \ 15871.61SkreATF_TC_HEAD(test, tc) \ 15881.61Skre{ \ 15891.61Skre atf_tc_set_md_var(tc, "descr", \ 15901.61Skre "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 15911.61Skre "vfork(2)ed child"); \ 15921.61Skre} \ 15931.61Skre \ 15941.61SkreATF_TC_BODY(test, tc) \ 15951.61Skre{ \ 15961.61Skre \ 15971.61Skre traceme_vfork_crash(sig); \ 15981.52Skamil} 15991.52Skamil 16001.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP) 16011.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV) 16021.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL) 16031.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE) 16041.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS) 16051.52Skamil 16061.41Skamil/// ---------------------------------------------------------------------------- 16071.41Skamil 16081.92Skamilstatic void 16091.92Skamiltraceme_vfork_signalmasked_crash(int sig) 16101.92Skamil{ 16111.92Skamil pid_t child, wpid; 16121.92Skamil#if defined(TWAIT_HAVE_STATUS) 16131.92Skamil int status; 16141.92Skamil#endif 16151.92Skamil sigset_t intmask; 16161.92Skamil 16171.92Skamil#ifndef PTRACE_ILLEGAL_ASM 16181.92Skamil if (sig == SIGILL) 16191.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 16201.92Skamil#endif 16211.92Skamil 16221.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 16231.114Skamil atf_tc_skip("FP exceptions are not supported"); 16241.114Skamil 16251.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 16261.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 16271.92Skamil if (child == 0) { 16281.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 16291.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 16301.92Skamil 16311.92Skamil sigemptyset(&intmask); 16321.92Skamil sigaddset(&intmask, sig); 16331.92Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 16341.92Skamil 16351.92Skamil DPRINTF("Before executing a trap\n"); 16361.92Skamil switch (sig) { 16371.92Skamil case SIGTRAP: 16381.92Skamil trigger_trap(); 16391.92Skamil break; 16401.92Skamil case SIGSEGV: 16411.92Skamil trigger_segv(); 16421.92Skamil break; 16431.92Skamil case SIGILL: 16441.92Skamil trigger_ill(); 16451.92Skamil break; 16461.92Skamil case SIGFPE: 16471.92Skamil trigger_fpe(); 16481.92Skamil break; 16491.92Skamil case SIGBUS: 16501.92Skamil trigger_bus(); 16511.92Skamil break; 16521.92Skamil default: 16531.92Skamil /* NOTREACHED */ 16541.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16551.92Skamil } 16561.92Skamil 16571.92Skamil /* NOTREACHED */ 16581.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16591.92Skamil } 16601.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 16611.92Skamil 16621.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16631.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 16641.92Skamil 16651.92Skamil validate_status_signaled(status, sig, 1); 16661.92Skamil 16671.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16681.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 16691.92Skamil} 16701.92Skamil 16711.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig) \ 16721.92SkamilATF_TC(test); \ 16731.92SkamilATF_TC_HEAD(test, tc) \ 16741.92Skamil{ \ 16751.92Skamil atf_tc_set_md_var(tc, "descr", \ 16761.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16771.92Skamil "vfork(2)ed child with a masked signal"); \ 16781.92Skamil} \ 16791.92Skamil \ 16801.92SkamilATF_TC_BODY(test, tc) \ 16811.92Skamil{ \ 16821.92Skamil \ 16831.92Skamil traceme_vfork_signalmasked_crash(sig); \ 16841.92Skamil} 16851.92Skamil 16861.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP) 16871.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV) 16881.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL) 16891.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE) 16901.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS) 16911.92Skamil 16921.92Skamil/// ---------------------------------------------------------------------------- 16931.92Skamil 16941.92Skamilstatic void 16951.92Skamiltraceme_vfork_signalignored_crash(int sig) 16961.92Skamil{ 16971.92Skamil pid_t child, wpid; 16981.92Skamil#if defined(TWAIT_HAVE_STATUS) 16991.92Skamil int status; 17001.92Skamil#endif 17011.92Skamil struct sigaction sa; 17021.92Skamil 17031.92Skamil#ifndef PTRACE_ILLEGAL_ASM 17041.92Skamil if (sig == SIGILL) 17051.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 17061.92Skamil#endif 17071.92Skamil 17081.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 17091.114Skamil atf_tc_skip("FP exceptions are not supported"); 17101.114Skamil 17111.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 17121.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 17131.92Skamil if (child == 0) { 17141.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 17151.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 17161.92Skamil 17171.92Skamil memset(&sa, 0, sizeof(sa)); 17181.92Skamil sa.sa_handler = SIG_IGN; 17191.92Skamil sigemptyset(&sa.sa_mask); 17201.92Skamil 17211.92Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 17221.92Skamil 17231.92Skamil DPRINTF("Before executing a trap\n"); 17241.92Skamil switch (sig) { 17251.92Skamil case SIGTRAP: 17261.92Skamil trigger_trap(); 17271.92Skamil break; 17281.92Skamil case SIGSEGV: 17291.92Skamil trigger_segv(); 17301.92Skamil break; 17311.92Skamil case SIGILL: 17321.92Skamil trigger_ill(); 17331.92Skamil break; 17341.92Skamil case SIGFPE: 17351.92Skamil trigger_fpe(); 17361.92Skamil break; 17371.92Skamil case SIGBUS: 17381.92Skamil trigger_bus(); 17391.92Skamil break; 17401.92Skamil default: 17411.92Skamil /* NOTREACHED */ 17421.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17431.92Skamil } 17441.92Skamil 17451.92Skamil /* NOTREACHED */ 17461.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17471.92Skamil } 17481.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 17491.92Skamil 17501.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17511.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17521.92Skamil 17531.92Skamil validate_status_signaled(status, sig, 1); 17541.92Skamil 17551.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17561.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 17571.92Skamil} 17581.92Skamil 17591.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig) \ 17601.92SkamilATF_TC(test); \ 17611.92SkamilATF_TC_HEAD(test, tc) \ 17621.92Skamil{ \ 17631.92Skamil atf_tc_set_md_var(tc, "descr", \ 17641.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 17651.92Skamil "vfork(2)ed child with ignored signal"); \ 17661.92Skamil} \ 17671.92Skamil \ 17681.92SkamilATF_TC_BODY(test, tc) \ 17691.92Skamil{ \ 17701.92Skamil \ 17711.92Skamil traceme_vfork_signalignored_crash(sig); \ 17721.92Skamil} 17731.92Skamil 17741.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap, 17751.92Skamil SIGTRAP) 17761.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv, 17771.92Skamil SIGSEGV) 17781.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill, 17791.92Skamil SIGILL) 17801.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe, 17811.92Skamil SIGFPE) 17821.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus, 17831.92Skamil SIGBUS) 17841.92Skamil 17851.92Skamil/// ---------------------------------------------------------------------------- 17861.92Skamil 17871.96Skamilstatic void 17881.96Skamiltraceme_vfork_exec(bool masked, bool ignored) 17891.43Skamil{ 17901.43Skamil const int sigval = SIGTRAP; 17911.43Skamil pid_t child, wpid; 17921.43Skamil#if defined(TWAIT_HAVE_STATUS) 17931.43Skamil int status; 17941.43Skamil#endif 17951.96Skamil struct sigaction sa; 17961.61Skre struct ptrace_siginfo info; 17971.96Skamil sigset_t intmask; 17981.96Skamil struct kinfo_proc2 kp; 17991.96Skamil size_t len = sizeof(kp); 18001.96Skamil 18011.96Skamil int name[6]; 18021.96Skamil const size_t namelen = __arraycount(name); 18031.96Skamil ki_sigset_t kp_sigmask; 18041.96Skamil ki_sigset_t kp_sigignore; 18051.43Skamil 18061.43Skamil memset(&info, 0, sizeof(info)); 18071.43Skamil 18081.43Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 18091.43Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 18101.43Skamil if (child == 0) { 18111.43Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 18121.43Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 18131.43Skamil 18141.96Skamil if (masked) { 18151.96Skamil sigemptyset(&intmask); 18161.96Skamil sigaddset(&intmask, sigval); 18171.96Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 18181.96Skamil } 18191.96Skamil 18201.96Skamil if (ignored) { 18211.96Skamil memset(&sa, 0, sizeof(sa)); 18221.96Skamil sa.sa_handler = SIG_IGN; 18231.96Skamil sigemptyset(&sa.sa_mask); 18241.96Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 18251.96Skamil } 18261.96Skamil 18271.43Skamil DPRINTF("Before calling execve(2) from child\n"); 18281.43Skamil execlp("/bin/echo", "/bin/echo", NULL); 18291.43Skamil 18301.43Skamil /* NOTREACHED */ 18311.43Skamil FORKEE_ASSERTX(0 && "Not reached"); 18321.43Skamil } 18331.43Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 18341.43Skamil 18351.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 18361.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 18371.43Skamil 18381.43Skamil validate_status_stopped(status, sigval); 18391.43Skamil 18401.96Skamil name[0] = CTL_KERN, 18411.96Skamil name[1] = KERN_PROC2, 18421.96Skamil name[2] = KERN_PROC_PID; 18431.96Skamil name[3] = getpid(); 18441.96Skamil name[4] = sizeof(kp); 18451.96Skamil name[5] = 1; 18461.96Skamil 18471.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18481.96Skamil 18491.96Skamil if (masked) 18501.96Skamil kp_sigmask = kp.p_sigmask; 18511.96Skamil 18521.96Skamil if (ignored) 18531.96Skamil kp_sigignore = kp.p_sigignore; 18541.96Skamil 18551.96Skamil name[3] = getpid(); 18561.96Skamil 18571.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18581.96Skamil 18591.96Skamil if (masked) { 18601.96Skamil DPRINTF("kp_sigmask=" 18611.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18621.96Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 18631.96Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 18641.96Skamil 18651.96Skamil DPRINTF("kp.p_sigmask=" 18661.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18671.96Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 18681.96Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 18691.96Skamil 18701.96Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 18711.96Skamil sizeof(kp_sigmask))); 18721.96Skamil } 18731.96Skamil 18741.96Skamil if (ignored) { 18751.96Skamil DPRINTF("kp_sigignore=" 18761.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18771.96Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 18781.96Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 18791.96Skamil 18801.96Skamil DPRINTF("kp.p_sigignore=" 18811.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18821.96Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 18831.96Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 18841.96Skamil 18851.96Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 18861.96Skamil sizeof(kp_sigignore))); 18871.96Skamil } 18881.96Skamil 18891.43Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 18901.61Skre SYSCALL_REQUIRE( 18911.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 18921.43Skamil 18931.43Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 18941.43Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 18951.43Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 18961.43Skamil info.psi_siginfo.si_errno); 18971.43Skamil 18981.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 18991.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 19001.43Skamil 19011.43Skamil DPRINTF("Before resuming the child process where it left off and " 19021.43Skamil "without signal to be sent\n"); 19031.43Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 19041.43Skamil 19051.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19061.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 19071.43Skamil 19081.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19091.43Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 19101.43Skamil} 19111.43Skamil 19121.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored) \ 19131.96SkamilATF_TC(test); \ 19141.96SkamilATF_TC_HEAD(test, tc) \ 19151.96Skamil{ \ 19161.96Skamil atf_tc_set_md_var(tc, "descr", \ 19171.96Skamil "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed " \ 19181.96Skamil "child%s%s", masked ? " with masked signal" : "", \ 19191.96Skamil masked ? " with ignored signal" : ""); \ 19201.96Skamil} \ 19211.96Skamil \ 19221.96SkamilATF_TC_BODY(test, tc) \ 19231.96Skamil{ \ 19241.96Skamil \ 19251.96Skamil traceme_vfork_exec(masked, ignored); \ 19261.96Skamil} 19271.96Skamil 19281.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false) 19291.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false) 19301.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true) 19311.96Skamil 19321.43Skamil/// ---------------------------------------------------------------------------- 19331.43Skamil 19341.1Skamil#if defined(TWAIT_HAVE_PID) 19351.51Skamilstatic void 19361.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored) 19371.59Skamil{ 19381.94Skamil const int sigval = SIGSTOP; 19391.59Skamil struct msg_fds parent_tracee, parent_tracer; 19401.59Skamil const int exitval = 10; 19411.59Skamil pid_t tracee, tracer, wpid; 19421.59Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 19431.59Skamil#if defined(TWAIT_HAVE_STATUS) 19441.59Skamil int status; 19451.59Skamil#endif 19461.94Skamil struct sigaction sa; 19471.59Skamil struct ptrace_siginfo info; 19481.94Skamil sigset_t intmask; 19491.94Skamil struct kinfo_proc2 kp; 19501.94Skamil size_t len = sizeof(kp); 19511.94Skamil 19521.94Skamil int name[6]; 19531.94Skamil const size_t namelen = __arraycount(name); 19541.94Skamil ki_sigset_t kp_sigmask; 19551.94Skamil ki_sigset_t kp_sigignore; 19561.61Skre 19571.71Skamil#ifndef PTRACE_ILLEGAL_ASM 19581.71Skamil if (sig == SIGILL) 19591.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 19601.71Skamil#endif 19611.71Skamil 19621.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 19631.114Skamil atf_tc_skip("FP exceptions are not supported"); 19641.114Skamil 19651.59Skamil memset(&info, 0, sizeof(info)); 19661.59Skamil 19671.59Skamil DPRINTF("Spawn tracee\n"); 19681.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 19691.59Skamil tracee = atf_utils_fork(); 19701.59Skamil if (tracee == 0) { 19711.59Skamil // Wait for parent to let us crash 19721.59Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 19731.61Skre 19741.94Skamil if (masked) { 19751.94Skamil sigemptyset(&intmask); 19761.94Skamil sigaddset(&intmask, sig); 19771.94Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 19781.94Skamil } 19791.94Skamil 19801.94Skamil if (ignored) { 19811.94Skamil memset(&sa, 0, sizeof(sa)); 19821.94Skamil sa.sa_handler = SIG_IGN; 19831.94Skamil sigemptyset(&sa.sa_mask); 19841.94Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 19851.94Skamil } 19861.94Skamil 19871.94Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 19881.94Skamil FORKEE_ASSERT(raise(sigval) == 0); 19891.94Skamil 19901.59Skamil DPRINTF("Before executing a trap\n"); 19911.59Skamil switch (sig) { 19921.59Skamil case SIGTRAP: 19931.59Skamil trigger_trap(); 19941.59Skamil break; 19951.59Skamil case SIGSEGV: 19961.59Skamil trigger_segv(); 19971.59Skamil break; 19981.59Skamil case SIGILL: 19991.59Skamil trigger_ill(); 20001.59Skamil break; 20011.59Skamil case SIGFPE: 20021.59Skamil trigger_fpe(); 20031.59Skamil break; 20041.59Skamil case SIGBUS: 20051.59Skamil trigger_bus(); 20061.59Skamil break; 20071.59Skamil default: 20081.59Skamil /* NOTREACHED */ 20091.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20101.59Skamil } 20111.59Skamil 20121.59Skamil /* NOTREACHED */ 20131.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20141.59Skamil } 20151.59Skamil 20161.59Skamil DPRINTF("Spawn debugger\n"); 20171.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 20181.59Skamil tracer = atf_utils_fork(); 20191.59Skamil if (tracer == 0) { 20201.59Skamil /* Fork again and drop parent to reattach to PID 1 */ 20211.59Skamil tracer = atf_utils_fork(); 20221.59Skamil if (tracer != 0) 20231.61Skre _exit(exitval); 20241.59Skamil 20251.59Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 20261.59Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 20271.59Skamil 20281.59Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 20291.59Skamil FORKEE_REQUIRE_SUCCESS( 20301.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20311.59Skamil 20321.59Skamil forkee_status_stopped(status, SIGSTOP); 20331.59Skamil 20341.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20351.94Skamil "traced process\n"); 20361.94Skamil SYSCALL_REQUIRE( 20371.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20381.94Skamil 20391.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20401.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20411.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20421.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20431.94Skamil 20441.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 20451.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 20461.94Skamil 20471.59Skamil /* Resume tracee with PT_CONTINUE */ 20481.59Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 20491.59Skamil 20501.59Skamil /* Inform parent that tracer has attached to tracee */ 20511.59Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 20521.59Skamil 20531.59Skamil /* Wait for parent to tell use that tracee should have exited */ 20541.59Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 20551.59Skamil 20561.59Skamil /* Wait for tracee and assert that it exited */ 20571.59Skamil FORKEE_REQUIRE_SUCCESS( 20581.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20591.59Skamil 20601.94Skamil forkee_status_stopped(status, sigval); 20611.94Skamil 20621.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20631.94Skamil "traced process\n"); 20641.94Skamil SYSCALL_REQUIRE( 20651.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20661.94Skamil 20671.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20681.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20691.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20701.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20711.94Skamil 20721.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 20731.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 20741.94Skamil 20751.94Skamil name[0] = CTL_KERN, 20761.94Skamil name[1] = KERN_PROC2, 20771.94Skamil name[2] = KERN_PROC_PID; 20781.94Skamil name[3] = tracee; 20791.94Skamil name[4] = sizeof(kp); 20801.94Skamil name[5] = 1; 20811.94Skamil 20821.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 20831.94Skamil 20841.94Skamil if (masked) 20851.94Skamil kp_sigmask = kp.p_sigmask; 20861.94Skamil 20871.94Skamil if (ignored) 20881.94Skamil kp_sigignore = kp.p_sigignore; 20891.94Skamil 20901.94Skamil /* Resume tracee with PT_CONTINUE */ 20911.94Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 20921.94Skamil 20931.94Skamil /* Wait for tracee and assert that it exited */ 20941.94Skamil FORKEE_REQUIRE_SUCCESS( 20951.94Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20961.94Skamil 20971.93Skamil forkee_status_stopped(status, sig); 20981.59Skamil 20991.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 21001.61Skre "traced process\n"); 21011.61Skre SYSCALL_REQUIRE( 21021.61Skre ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 21031.59Skamil 21041.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21051.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21061.61Skre "si_errno=%#x\n", info.psi_siginfo.si_signo, 21071.61Skre info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 21081.59Skamil 21091.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig); 21101.94Skamil 21111.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21121.94Skamil 21131.94Skamil if (masked) { 21141.94Skamil DPRINTF("kp_sigmask=" 21151.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21161.94Skamil PRIx32 "\n", 21171.94Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 21181.94Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 21191.94Skamil 21201.94Skamil DPRINTF("kp.p_sigmask=" 21211.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21221.94Skamil PRIx32 "\n", 21231.94Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 21241.94Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 21251.94Skamil 21261.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask, 21271.94Skamil sizeof(kp_sigmask))); 21281.94Skamil } 21291.94Skamil 21301.94Skamil if (ignored) { 21311.94Skamil DPRINTF("kp_sigignore=" 21321.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21331.94Skamil PRIx32 "\n", 21341.94Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 21351.94Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 21361.94Skamil 21371.94Skamil DPRINTF("kp.p_sigignore=" 21381.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21391.94Skamil PRIx32 "\n", 21401.94Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 21411.94Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 21421.94Skamil 21431.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore, 21441.94Skamil sizeof(kp_sigignore))); 21451.94Skamil } 21461.94Skamil 21471.59Skamil switch (sig) { 21481.59Skamil case SIGTRAP: 21491.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 21501.59Skamil break; 21511.59Skamil case SIGSEGV: 21521.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 21531.59Skamil break; 21541.71Skamil case SIGILL: 21551.113Skamil FORKEE_ASSERT(info.psi_siginfo.si_code >= ILL_ILLOPC && 21561.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 21571.71Skamil break; 21581.59Skamil case SIGFPE: 21591.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 21601.59Skamil break; 21611.59Skamil case SIGBUS: 21621.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 21631.59Skamil break; 21641.59Skamil } 21651.59Skamil 21661.59Skamil FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1); 21671.59Skamil DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME); 21681.93Skamil FORKEE_REQUIRE_SUCCESS( 21691.61Skre wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21701.59Skamil 21711.93Skamil forkee_status_signaled(status, SIGKILL, 0); 21721.59Skamil 21731.71Skamil /* Inform parent that tracer is exiting normally */ 21741.71Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 21751.71Skamil 21761.59Skamil DPRINTF("Before exiting of the tracer process\n"); 21771.59Skamil _exit(0 /* collect by initproc */); 21781.59Skamil } 21791.59Skamil 21801.59Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 21811.59Skamil "calling %s()\n", TWAIT_FNAME); 21821.59Skamil TWAIT_REQUIRE_SUCCESS( 21831.59Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 21841.59Skamil 21851.59Skamil validate_status_exited(status, exitval); 21861.59Skamil 21871.59Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 21881.59Skamil TWAIT_FNAME); 21891.59Skamil TWAIT_REQUIRE_SUCCESS( 21901.59Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 21911.59Skamil 21921.59Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 21931.59Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 21941.59Skamil 21951.59Skamil DPRINTF("Resume the tracee and let it crash\n"); 21961.59Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 21971.59Skamil 21981.59Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 21991.59Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 22001.59Skamil 22011.59Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 22021.59Skamil TWAIT_FNAME); 22031.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22041.59Skamil 22051.59Skamil validate_status_signaled(status, SIGKILL, 0); 22061.59Skamil 22071.71Skamil DPRINTF("Await normal exit of tracer\n"); 22081.71Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 22091.71Skamil 22101.59Skamil msg_close(&parent_tracer); 22111.59Skamil msg_close(&parent_tracee); 22121.59Skamil} 22131.59Skamil 22141.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig) \ 22151.61SkreATF_TC(test); \ 22161.61SkreATF_TC_HEAD(test, tc) \ 22171.61Skre{ \ 22181.61Skre atf_tc_set_md_var(tc, "descr", \ 22191.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22201.94Skamil "the debuggee"); \ 22211.61Skre} \ 22221.61Skre \ 22231.61SkreATF_TC_BODY(test, tc) \ 22241.61Skre{ \ 22251.61Skre \ 22261.94Skamil unrelated_tracer_sees_crash(sig, false, false); \ 22271.59Skamil} 22281.59Skamil 22291.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP) 22301.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV) 22311.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL) 22321.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE) 22331.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS) 22341.94Skamil 22351.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig) \ 22361.94SkamilATF_TC(test); \ 22371.94SkamilATF_TC_HEAD(test, tc) \ 22381.94Skamil{ \ 22391.94Skamil atf_tc_set_md_var(tc, "descr", \ 22401.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22411.94Skamil "the debuggee with masked signal"); \ 22421.94Skamil} \ 22431.94Skamil \ 22441.94SkamilATF_TC_BODY(test, tc) \ 22451.94Skamil{ \ 22461.94Skamil \ 22471.94Skamil unrelated_tracer_sees_crash(sig, true, false); \ 22481.94Skamil} 22491.94Skamil 22501.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22511.94Skamil unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP) 22521.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22531.94Skamil unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV) 22541.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22551.94Skamil unrelated_tracer_sees_signalmasked_crash_ill, SIGILL) 22561.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22571.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE) 22581.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22591.94Skamil unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS) 22601.94Skamil 22611.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig) \ 22621.94SkamilATF_TC(test); \ 22631.94SkamilATF_TC_HEAD(test, tc) \ 22641.94Skamil{ \ 22651.94Skamil atf_tc_set_md_var(tc, "descr", \ 22661.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22671.94Skamil "the debuggee with signal ignored"); \ 22681.94Skamil} \ 22691.94Skamil \ 22701.94SkamilATF_TC_BODY(test, tc) \ 22711.94Skamil{ \ 22721.94Skamil \ 22731.94Skamil unrelated_tracer_sees_crash(sig, false, true); \ 22741.94Skamil} 22751.94Skamil 22761.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22771.94Skamil unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP) 22781.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22791.94Skamil unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV) 22801.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22811.94Skamil unrelated_tracer_sees_signalignored_crash_ill, SIGILL) 22821.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22831.94Skamil unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE) 22841.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22851.94Skamil unrelated_tracer_sees_signalignored_crash_bus, SIGBUS) 22861.59Skamil#endif 22871.59Skamil 22881.59Skamil/// ---------------------------------------------------------------------------- 22891.59Skamil 22901.59Skamil#if defined(TWAIT_HAVE_PID) 22911.59Skamilstatic void 22921.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated, 22931.67Skamil bool stopped) 22941.1Skamil{ 22951.51Skamil /* 22961.51Skamil * notimeout - disable timeout in await zombie function 22971.51Skamil * unrelated - attach from unrelated tracer reparented to initproc 22981.67Skamil * stopped - attach to a stopped process 22991.51Skamil */ 23001.1Skamil 23011.1Skamil struct msg_fds parent_tracee, parent_tracer; 23021.1Skamil const int exitval_tracee = 5; 23031.1Skamil const int exitval_tracer = 10; 23041.1Skamil pid_t tracee, tracer, wpid; 23051.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 23061.1Skamil#if defined(TWAIT_HAVE_STATUS) 23071.1Skamil int status; 23081.1Skamil#endif 23091.1Skamil 23101.67Skamil /* 23111.67Skamil * Only a subset of options are supported. 23121.67Skamil */ 23131.67Skamil ATF_REQUIRE((!notimeout && !unrelated && !stopped) || 23141.67Skamil (!notimeout && unrelated && !stopped) || 23151.67Skamil (notimeout && !unrelated && !stopped) || 23161.67Skamil (!notimeout && unrelated && stopped)); 23171.67Skamil 23181.13Schristos DPRINTF("Spawn tracee\n"); 23191.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 23201.1Skamil tracee = atf_utils_fork(); 23211.1Skamil if (tracee == 0) { 23221.67Skamil if (stopped) { 23231.67Skamil DPRINTF("Stop self PID %d\n", getpid()); 23241.67Skamil raise(SIGSTOP); 23251.67Skamil } 23261.67Skamil 23271.1Skamil // Wait for parent to let us exit 23281.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 23291.1Skamil _exit(exitval_tracee); 23301.1Skamil } 23311.1Skamil 23321.13Schristos DPRINTF("Spawn debugger\n"); 23331.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 23341.1Skamil tracer = atf_utils_fork(); 23351.1Skamil if (tracer == 0) { 23361.51Skamil if(unrelated) { 23371.51Skamil /* Fork again and drop parent to reattach to PID 1 */ 23381.51Skamil tracer = atf_utils_fork(); 23391.51Skamil if (tracer != 0) 23401.51Skamil _exit(exitval_tracer); 23411.51Skamil } 23421.51Skamil 23431.67Skamil if (stopped) { 23441.67Skamil DPRINTF("Await for a stopped parent PID %d\n", tracee); 23451.67Skamil await_stopped(tracee); 23461.67Skamil } 23471.67Skamil 23481.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 23491.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 23501.1Skamil 23511.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 23521.1Skamil FORKEE_REQUIRE_SUCCESS( 23531.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23541.1Skamil 23551.1Skamil forkee_status_stopped(status, SIGSTOP); 23561.1Skamil 23571.1Skamil /* Resume tracee with PT_CONTINUE */ 23581.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 23591.1Skamil 23601.1Skamil /* Inform parent that tracer has attached to tracee */ 23611.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 23621.1Skamil 23631.1Skamil /* Wait for parent to tell use that tracee should have exited */ 23641.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 23651.1Skamil 23661.1Skamil /* Wait for tracee and assert that it exited */ 23671.1Skamil FORKEE_REQUIRE_SUCCESS( 23681.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23691.1Skamil 23701.1Skamil forkee_status_exited(status, exitval_tracee); 23711.13Schristos DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee); 23721.1Skamil 23731.13Schristos DPRINTF("Before exiting of the tracer process\n"); 23741.51Skamil _exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer); 23751.51Skamil } 23761.51Skamil 23771.51Skamil if (unrelated) { 23781.51Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 23791.51Skamil "calling %s()\n", TWAIT_FNAME); 23801.51Skamil TWAIT_REQUIRE_SUCCESS( 23811.51Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 23821.51Skamil 23831.51Skamil validate_status_exited(status, exitval_tracer); 23841.51Skamil 23851.51Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 23861.51Skamil TWAIT_FNAME); 23871.51Skamil TWAIT_REQUIRE_SUCCESS( 23881.51Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 23891.1Skamil } 23901.1Skamil 23911.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 23921.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 23931.1Skamil 23941.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 23951.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 23961.1Skamil 23971.13Schristos DPRINTF("Detect that tracee is zombie\n"); 23981.51Skamil if (notimeout) 23991.26Skamil await_zombie_raw(tracee, 0); 24001.26Skamil else 24011.26Skamil await_zombie(tracee); 24021.1Skamil 24031.13Schristos DPRINTF("Assert that there is no status about tracee %d - " 24041.1Skamil "Tracer must detect zombie first - calling %s()\n", tracee, 24051.1Skamil TWAIT_FNAME); 24061.1Skamil TWAIT_REQUIRE_SUCCESS( 24071.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 24081.1Skamil 24091.51Skamil if (unrelated) { 24101.51Skamil DPRINTF("Resume the tracer and let it detect exited tracee\n"); 24111.51Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 24121.51Skamil } else { 24131.51Skamil DPRINTF("Tell the tracer child should have exited\n"); 24141.51Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 24151.51Skamil DPRINTF("Wait for tracer to finish its job and exit - calling " 24161.59Skamil "%s()\n", TWAIT_FNAME); 24171.51Skamil 24181.51Skamil DPRINTF("Wait from tracer child to complete waiting for " 24191.59Skamil "tracee\n"); 24201.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 24211.51Skamil tracer); 24221.1Skamil 24231.51Skamil validate_status_exited(status, exitval_tracer); 24241.51Skamil } 24251.1Skamil 24261.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 24271.1Skamil TWAIT_FNAME); 24281.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24291.1Skamil 24301.1Skamil validate_status_exited(status, exitval_tracee); 24311.1Skamil 24321.1Skamil msg_close(&parent_tracer); 24331.1Skamil msg_close(&parent_tracee); 24341.1Skamil} 24351.26Skamil 24361.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent); 24371.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc) 24381.51Skamil{ 24391.51Skamil atf_tc_set_md_var(tc, "descr", 24401.51Skamil "Assert that tracer sees process termination before the parent"); 24411.51Skamil} 24421.51Skamil 24431.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc) 24441.26Skamil{ 24451.26Skamil 24461.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, false, false); 24471.26Skamil} 24481.26Skamil 24491.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates); 24501.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc) 24511.1Skamil{ 24521.1Skamil atf_tc_set_md_var(tc, "descr", 24531.51Skamil "Assert that await_zombie() in attach1 always finds a single " 24541.51Skamil "process and no other error is reported"); 24551.1Skamil} 24561.1Skamil 24571.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc) 24581.1Skamil{ 24591.51Skamil time_t start, end; 24601.51Skamil double diff; 24611.51Skamil unsigned long N = 0; 24621.1Skamil 24631.51Skamil /* 24641.51Skamil * Reuse this test with tracer_sees_terminaton_before_the_parent_raw(). 24651.51Skamil * This test body isn't specific to this race, however it's just good 24661.51Skamil * enough for this purposes, no need to invent a dedicated code flow. 24671.51Skamil */ 24681.1Skamil 24691.51Skamil start = time(NULL); 24701.51Skamil while (true) { 24711.51Skamil DPRINTF("Step: %lu\n", N); 24721.67Skamil tracer_sees_terminaton_before_the_parent_raw(true, false, 24731.67Skamil false); 24741.51Skamil end = time(NULL); 24751.51Skamil diff = difftime(end, start); 24761.51Skamil if (diff >= 5.0) 24771.51Skamil break; 24781.51Skamil ++N; 24791.1Skamil } 24801.51Skamil DPRINTF("Iterations: %lu\n", N); 24811.51Skamil} 24821.1Skamil 24831.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent); 24841.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc) 24851.51Skamil{ 24861.51Skamil atf_tc_set_md_var(tc, "descr", 24871.51Skamil "Assert that tracer sees process termination before the parent"); 24881.51Skamil} 24891.1Skamil 24901.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc) 24911.51Skamil{ 24921.1Skamil 24931.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, false); 24941.67Skamil} 24951.67Skamil 24961.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process); 24971.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc) 24981.67Skamil{ 24991.67Skamil atf_tc_set_md_var(tc, "descr", 25001.67Skamil "Assert that tracer can attach to an unrelated stopped process"); 25011.67Skamil} 25021.67Skamil 25031.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc) 25041.67Skamil{ 25051.67Skamil 25061.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, true); 25071.1Skamil} 25081.1Skamil#endif 25091.1Skamil 25101.51Skamil/// ---------------------------------------------------------------------------- 25111.51Skamil 25121.66Skamilstatic void 25131.66Skamilparent_attach_to_its_child(bool stopped) 25141.1Skamil{ 25151.1Skamil struct msg_fds parent_tracee; 25161.1Skamil const int exitval_tracee = 5; 25171.1Skamil pid_t tracee, wpid; 25181.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 25191.1Skamil#if defined(TWAIT_HAVE_STATUS) 25201.1Skamil int status; 25211.1Skamil#endif 25221.1Skamil 25231.13Schristos DPRINTF("Spawn tracee\n"); 25241.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 25251.1Skamil tracee = atf_utils_fork(); 25261.1Skamil if (tracee == 0) { 25271.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 25281.13Schristos DPRINTF("Parent should now attach to tracee\n"); 25291.1Skamil 25301.66Skamil if (stopped) { 25311.66Skamil DPRINTF("Stop self PID %d\n", getpid()); 25321.66Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 25331.66Skamil } 25341.66Skamil 25351.1Skamil CHILD_FROM_PARENT("Message 2", parent_tracee, msg); 25361.1Skamil /* Wait for message from the parent */ 25371.1Skamil _exit(exitval_tracee); 25381.1Skamil } 25391.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 25401.57Skamil 25411.66Skamil if (stopped) { 25421.66Skamil DPRINTF("Await for a stopped tracee PID %d\n", tracee); 25431.66Skamil await_stopped(tracee); 25441.66Skamil } 25451.66Skamil 25461.13Schristos DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee); 25471.13Schristos SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 25481.1Skamil 25491.13Schristos DPRINTF("Wait for the stopped tracee process with %s()\n", 25501.1Skamil TWAIT_FNAME); 25511.1Skamil TWAIT_REQUIRE_SUCCESS( 25521.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25531.1Skamil 25541.1Skamil validate_status_stopped(status, SIGSTOP); 25551.1Skamil 25561.13Schristos DPRINTF("Resume tracee with PT_CONTINUE\n"); 25571.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 25581.1Skamil 25591.13Schristos DPRINTF("Let the tracee exit now\n"); 25601.1Skamil PARENT_TO_CHILD("Message 2", parent_tracee, msg); 25611.1Skamil 25621.13Schristos DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME); 25631.1Skamil TWAIT_REQUIRE_SUCCESS( 25641.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25651.1Skamil 25661.1Skamil validate_status_exited(status, exitval_tracee); 25671.1Skamil 25681.13Schristos DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME); 25691.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 25701.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0)); 25711.1Skamil 25721.1Skamil msg_close(&parent_tracee); 25731.1Skamil} 25741.1Skamil 25751.66SkamilATF_TC(parent_attach_to_its_child); 25761.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc) 25771.66Skamil{ 25781.66Skamil atf_tc_set_md_var(tc, "descr", 25791.66Skamil "Assert that tracer parent can PT_ATTACH to its child"); 25801.66Skamil} 25811.66Skamil 25821.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc) 25831.66Skamil{ 25841.66Skamil 25851.66Skamil parent_attach_to_its_child(false); 25861.66Skamil} 25871.66Skamil 25881.66SkamilATF_TC(parent_attach_to_its_stopped_child); 25891.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc) 25901.66Skamil{ 25911.66Skamil atf_tc_set_md_var(tc, "descr", 25921.66Skamil "Assert that tracer parent can PT_ATTACH to its stopped child"); 25931.66Skamil} 25941.66Skamil 25951.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc) 25961.66Skamil{ 25971.66Skamil 25981.66Skamil parent_attach_to_its_child(true); 25991.66Skamil} 26001.66Skamil 26011.51Skamil/// ---------------------------------------------------------------------------- 26021.51Skamil 26031.65Skamilstatic void 26041.65Skamilchild_attach_to_its_parent(bool stopped) 26051.1Skamil{ 26061.1Skamil struct msg_fds parent_tracee; 26071.1Skamil const int exitval_tracer = 5; 26081.1Skamil pid_t tracer, wpid; 26091.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 26101.1Skamil#if defined(TWAIT_HAVE_STATUS) 26111.1Skamil int status; 26121.1Skamil#endif 26131.1Skamil 26141.13Schristos DPRINTF("Spawn tracer\n"); 26151.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 26161.1Skamil tracer = atf_utils_fork(); 26171.1Skamil if (tracer == 0) { 26181.1Skamil /* Wait for message from the parent */ 26191.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 26201.1Skamil 26211.65Skamil if (stopped) { 26221.65Skamil DPRINTF("Await for a stopped parent PID %d\n", 26231.65Skamil getppid()); 26241.65Skamil await_stopped(getppid()); 26251.65Skamil } 26261.65Skamil 26271.13Schristos DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n", 26281.1Skamil getppid()); 26291.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1); 26301.1Skamil 26311.13Schristos DPRINTF("Wait for the stopped parent process with %s()\n", 26321.1Skamil TWAIT_FNAME); 26331.1Skamil FORKEE_REQUIRE_SUCCESS( 26341.1Skamil wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid()); 26351.1Skamil 26361.1Skamil forkee_status_stopped(status, SIGSTOP); 26371.1Skamil 26381.13Schristos DPRINTF("Resume parent with PT_DETACH\n"); 26391.1Skamil FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0) 26401.1Skamil != -1); 26411.1Skamil 26421.1Skamil /* Tell parent we are ready */ 26431.1Skamil CHILD_TO_PARENT("Message 1", parent_tracee, msg); 26441.1Skamil 26451.1Skamil _exit(exitval_tracer); 26461.1Skamil } 26471.1Skamil 26481.13Schristos DPRINTF("Wait for the tracer to become ready\n"); 26491.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 26501.65Skamil 26511.65Skamil if (stopped) { 26521.65Skamil DPRINTF("Stop self PID %d\n", getpid()); 26531.65Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 26541.65Skamil } 26551.65Skamil 26561.13Schristos DPRINTF("Allow the tracer to exit now\n"); 26571.1Skamil PARENT_FROM_CHILD("Message 1", parent_tracee, msg); 26581.1Skamil 26591.13Schristos DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME); 26601.1Skamil TWAIT_REQUIRE_SUCCESS( 26611.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 26621.1Skamil 26631.1Skamil validate_status_exited(status, exitval_tracer); 26641.1Skamil 26651.13Schristos DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME); 26661.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 26671.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0)); 26681.1Skamil 26691.1Skamil msg_close(&parent_tracee); 26701.1Skamil} 26711.1Skamil 26721.65SkamilATF_TC(child_attach_to_its_parent); 26731.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc) 26741.65Skamil{ 26751.65Skamil atf_tc_set_md_var(tc, "descr", 26761.65Skamil "Assert that tracer child can PT_ATTACH to its parent"); 26771.65Skamil} 26781.65Skamil 26791.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc) 26801.65Skamil{ 26811.65Skamil 26821.65Skamil child_attach_to_its_parent(false); 26831.65Skamil} 26841.65Skamil 26851.65SkamilATF_TC(child_attach_to_its_stopped_parent); 26861.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc) 26871.65Skamil{ 26881.65Skamil atf_tc_set_md_var(tc, "descr", 26891.65Skamil "Assert that tracer child can PT_ATTACH to its stopped parent"); 26901.65Skamil} 26911.65Skamil 26921.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc) 26931.65Skamil{ 26941.65Skamil /* 26951.65Skamil * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as 26961.65Skamil * this causes a pipe (established from atf-run) to be broken. 26971.65Skamil * atf-run uses this mechanism to monitor whether a test is alive. 26981.65Skamil * 26991.65Skamil * As a workaround spawn this test as a subprocess. 27001.65Skamil */ 27011.65Skamil 27021.65Skamil const int exitval = 15; 27031.65Skamil pid_t child, wpid; 27041.65Skamil#if defined(TWAIT_HAVE_STATUS) 27051.65Skamil int status; 27061.65Skamil#endif 27071.65Skamil 27081.65Skamil SYSCALL_REQUIRE((child = fork()) != -1); 27091.65Skamil if (child == 0) { 27101.65Skamil child_attach_to_its_parent(true); 27111.65Skamil _exit(exitval); 27121.65Skamil } else { 27131.65Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 27141.65Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 27151.65Skamil 27161.65Skamil validate_status_exited(status, exitval); 27171.65Skamil 27181.65Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 27191.65Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 27201.65Skamil } 27211.65Skamil} 27221.65Skamil 27231.51Skamil/// ---------------------------------------------------------------------------- 27241.51Skamil 27251.1Skamil#if defined(TWAIT_HAVE_PID) 27261.1Skamil 27271.51Skamilenum tracee_sees_its_original_parent_type { 27281.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 27291.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 27301.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS 27311.51Skamil}; 27321.51Skamil 27331.51Skamilstatic void 27341.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type) 27351.1Skamil{ 27361.1Skamil struct msg_fds parent_tracer, parent_tracee; 27371.1Skamil const int exitval_tracee = 5; 27381.1Skamil const int exitval_tracer = 10; 27391.1Skamil pid_t parent, tracee, tracer, wpid; 27401.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 27411.1Skamil#if defined(TWAIT_HAVE_STATUS) 27421.1Skamil int status; 27431.1Skamil#endif 27441.51Skamil /* sysctl(3) - kinfo_proc2 */ 27451.51Skamil int name[CTL_MAXNAME]; 27461.51Skamil struct kinfo_proc2 kp; 27471.51Skamil size_t len = sizeof(kp); 27481.51Skamil unsigned int namelen; 27491.51Skamil 27501.51Skamil /* procfs - status */ 27511.51Skamil FILE *fp; 27521.51Skamil struct stat st; 27531.51Skamil const char *fname = "/proc/curproc/status"; 27541.51Skamil char s_executable[MAXPATHLEN]; 27551.51Skamil int s_pid, s_ppid; 27561.51Skamil int rv; 27571.51Skamil 27581.51Skamil if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) { 27591.61Skre SYSCALL_REQUIRE( 27601.61Skre (rv = stat(fname, &st)) == 0 || (errno == ENOENT)); 27611.61Skre if (rv != 0) 27621.51Skamil atf_tc_skip("/proc/curproc/status not found"); 27631.51Skamil } 27641.1Skamil 27651.13Schristos DPRINTF("Spawn tracee\n"); 27661.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 27671.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 27681.1Skamil tracee = atf_utils_fork(); 27691.1Skamil if (tracee == 0) { 27701.1Skamil parent = getppid(); 27711.1Skamil 27721.1Skamil /* Emit message to the parent */ 27731.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 27741.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 27751.1Skamil 27761.51Skamil switch (type) { 27771.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID: 27781.51Skamil FORKEE_ASSERT_EQ(parent, getppid()); 27791.51Skamil break; 27801.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2: 27811.51Skamil namelen = 0; 27821.51Skamil name[namelen++] = CTL_KERN; 27831.51Skamil name[namelen++] = KERN_PROC2; 27841.51Skamil name[namelen++] = KERN_PROC_PID; 27851.51Skamil name[namelen++] = getpid(); 27861.51Skamil name[namelen++] = len; 27871.51Skamil name[namelen++] = 1; 27881.51Skamil 27891.61Skre FORKEE_ASSERT_EQ( 27901.61Skre sysctl(name, namelen, &kp, &len, NULL, 0), 0); 27911.51Skamil FORKEE_ASSERT_EQ(parent, kp.p_ppid); 27921.51Skamil break; 27931.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS: 27941.51Skamil /* 27951.51Skamil * Format: 27961.51Skamil * EXECUTABLE PID PPID ... 27971.51Skamil */ 27981.51Skamil FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL); 27991.51Skamil fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid); 28001.51Skamil FORKEE_ASSERT_EQ(fclose(fp), 0); 28011.51Skamil FORKEE_ASSERT_EQ(parent, s_ppid); 28021.51Skamil break; 28031.51Skamil } 28041.1Skamil 28051.1Skamil _exit(exitval_tracee); 28061.1Skamil } 28071.13Schristos DPRINTF("Wait for child to record its parent identifier (pid)\n"); 28081.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 28091.1Skamil 28101.13Schristos DPRINTF("Spawn debugger\n"); 28111.1Skamil tracer = atf_utils_fork(); 28121.1Skamil if (tracer == 0) { 28131.1Skamil /* No IPC to communicate with the child */ 28141.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 28151.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 28161.1Skamil 28171.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 28181.1Skamil FORKEE_REQUIRE_SUCCESS( 28191.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28201.1Skamil 28211.1Skamil forkee_status_stopped(status, SIGSTOP); 28221.1Skamil 28231.1Skamil /* Resume tracee with PT_CONTINUE */ 28241.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 28251.1Skamil 28261.1Skamil /* Inform parent that tracer has attached to tracee */ 28271.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 28281.1Skamil 28291.1Skamil /* Wait for parent to tell use that tracee should have exited */ 28301.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 28311.1Skamil 28321.1Skamil /* Wait for tracee and assert that it exited */ 28331.1Skamil FORKEE_REQUIRE_SUCCESS( 28341.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28351.1Skamil 28361.1Skamil forkee_status_exited(status, exitval_tracee); 28371.1Skamil 28381.13Schristos DPRINTF("Before exiting of the tracer process\n"); 28391.1Skamil _exit(exitval_tracer); 28401.1Skamil } 28411.1Skamil 28421.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 28431.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 28441.1Skamil 28451.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 28461.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 28471.1Skamil 28481.13Schristos DPRINTF("Detect that tracee is zombie\n"); 28491.1Skamil await_zombie(tracee); 28501.1Skamil 28511.13Schristos DPRINTF("Assert that there is no status about tracee - " 28521.1Skamil "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME); 28531.1Skamil TWAIT_REQUIRE_SUCCESS( 28541.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 28551.1Skamil 28561.13Schristos DPRINTF("Tell the tracer child should have exited\n"); 28571.1Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 28581.1Skamil 28591.13Schristos DPRINTF("Wait from tracer child to complete waiting for tracee\n"); 28601.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 28611.1Skamil tracer); 28621.1Skamil 28631.1Skamil validate_status_exited(status, exitval_tracer); 28641.1Skamil 28651.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 28661.1Skamil TWAIT_FNAME); 28671.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 28681.1Skamil tracee); 28691.1Skamil 28701.1Skamil validate_status_exited(status, exitval_tracee); 28711.1Skamil 28721.1Skamil msg_close(&parent_tracer); 28731.1Skamil msg_close(&parent_tracee); 28741.1Skamil} 28751.1Skamil 28761.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr) \ 28771.61SkreATF_TC(test); \ 28781.61SkreATF_TC_HEAD(test, tc) \ 28791.61Skre{ \ 28801.61Skre atf_tc_set_md_var(tc, "descr", \ 28811.61Skre "Assert that tracee sees its original parent when being traced " \ 28821.61Skre "(check " descr ")"); \ 28831.61Skre} \ 28841.61Skre \ 28851.61SkreATF_TC_BODY(test, tc) \ 28861.61Skre{ \ 28871.61Skre \ 28881.61Skre tracee_sees_its_original_parent(type); \ 28891.1Skamil} 28901.1Skamil 28911.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 28921.51Skamil tracee_sees_its_original_parent_getppid, 28931.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 28941.51Skamil "getppid(2)"); 28951.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 28961.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2, 28971.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 28981.51Skamil "sysctl(3) and kinfo_proc2"); 28991.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29001.51Skamil tracee_sees_its_original_parent_procfs_status, 29011.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS, 29021.51Skamil "the status file in procfs"); 29031.1Skamil#endif 29041.1Skamil 29051.51Skamil/// ---------------------------------------------------------------------------- 29061.1Skamil 29071.53Skamilstatic void 29081.53Skamileventmask_preserved(int event) 29091.1Skamil{ 29101.1Skamil const int exitval = 5; 29111.1Skamil const int sigval = SIGSTOP; 29121.1Skamil pid_t child, wpid; 29131.1Skamil#if defined(TWAIT_HAVE_STATUS) 29141.1Skamil int status; 29151.1Skamil#endif 29161.1Skamil ptrace_event_t set_event, get_event; 29171.1Skamil const int len = sizeof(ptrace_event_t); 29181.1Skamil 29191.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 29201.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 29211.1Skamil if (child == 0) { 29221.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 29231.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 29241.1Skamil 29251.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 29261.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 29271.1Skamil 29281.13Schristos DPRINTF("Before exiting of the child process\n"); 29291.1Skamil _exit(exitval); 29301.1Skamil } 29311.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 29321.1Skamil 29331.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29341.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29351.1Skamil 29361.1Skamil validate_status_stopped(status, sigval); 29371.1Skamil 29381.53Skamil set_event.pe_set_event = event; 29391.61Skre SYSCALL_REQUIRE( 29401.61Skre ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); 29411.61Skre SYSCALL_REQUIRE( 29421.61Skre ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); 29431.1Skamil ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); 29441.1Skamil 29451.13Schristos DPRINTF("Before resuming the child process where it left off and " 29461.1Skamil "without signal to be sent\n"); 29471.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 29481.1Skamil 29491.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29501.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29511.1Skamil 29521.1Skamil validate_status_exited(status, exitval); 29531.1Skamil 29541.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29551.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 29561.1Skamil} 29571.1Skamil 29581.61Skre#define EVENTMASK_PRESERVED(test, event) \ 29591.61SkreATF_TC(test); \ 29601.61SkreATF_TC_HEAD(test, tc) \ 29611.61Skre{ \ 29621.61Skre atf_tc_set_md_var(tc, "descr", \ 29631.61Skre "Verify that eventmask " #event " is preserved"); \ 29641.61Skre} \ 29651.61Skre \ 29661.61SkreATF_TC_BODY(test, tc) \ 29671.61Skre{ \ 29681.61Skre \ 29691.61Skre eventmask_preserved(event); \ 29701.1Skamil} 29711.1Skamil 29721.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0) 29731.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK) 29741.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK) 29751.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE) 29761.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE) 29771.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT) 29781.1Skamil 29791.53Skamil/// ---------------------------------------------------------------------------- 29801.1Skamil 29811.28Skamilstatic void 29821.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork, 29831.105Skamil bool trackvforkdone) 29841.1Skamil{ 29851.1Skamil const int exitval = 5; 29861.1Skamil const int exitval2 = 15; 29871.1Skamil const int sigval = SIGSTOP; 29881.31Skamil pid_t child, child2 = 0, wpid; 29891.1Skamil#if defined(TWAIT_HAVE_STATUS) 29901.1Skamil int status; 29911.1Skamil#endif 29921.1Skamil ptrace_state_t state; 29931.1Skamil const int slen = sizeof(state); 29941.1Skamil ptrace_event_t event; 29951.1Skamil const int elen = sizeof(event); 29961.1Skamil 29971.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 29981.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 29991.1Skamil if (child == 0) { 30001.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 30011.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 30021.1Skamil 30031.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 30041.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 30051.1Skamil 30061.30Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 30071.1Skamil 30081.1Skamil if (child2 == 0) 30091.1Skamil _exit(exitval2); 30101.1Skamil 30111.1Skamil FORKEE_REQUIRE_SUCCESS 30121.1Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 30131.1Skamil 30141.1Skamil forkee_status_exited(status, exitval2); 30151.1Skamil 30161.13Schristos DPRINTF("Before exiting of the child process\n"); 30171.1Skamil _exit(exitval); 30181.1Skamil } 30191.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 30201.1Skamil 30211.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 30221.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 30231.1Skamil 30241.1Skamil validate_status_stopped(status, sigval); 30251.1Skamil 30261.30Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 30271.61Skre trackfork ? "|PTRACE_FORK" : "", 30281.61Skre trackvfork ? "|PTRACE_VFORK" : "", 30291.61Skre trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 30301.30Skamil event.pe_set_event = 0; 30311.30Skamil if (trackfork) 30321.30Skamil event.pe_set_event |= PTRACE_FORK; 30331.30Skamil if (trackvfork) 30341.30Skamil event.pe_set_event |= PTRACE_VFORK; 30351.30Skamil if (trackvforkdone) 30361.30Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 30371.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 30381.1Skamil 30391.13Schristos DPRINTF("Before resuming the child process where it left off and " 30401.1Skamil "without signal to be sent\n"); 30411.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 30421.1Skamil 30431.29Skamil#if defined(TWAIT_HAVE_PID) 30441.31Skamil if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) { 30451.29Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 30461.61Skre child); 30471.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 30481.61Skre child); 30491.1Skamil 30501.29Skamil validate_status_stopped(status, SIGTRAP); 30511.1Skamil 30521.61Skre SYSCALL_REQUIRE( 30531.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 30541.31Skamil if (trackfork && fn == fork) { 30551.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 30561.30Skamil PTRACE_FORK); 30571.30Skamil } 30581.31Skamil if (trackvfork && fn == vfork) { 30591.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 30601.30Skamil PTRACE_VFORK); 30611.30Skamil } 30621.29Skamil 30631.29Skamil child2 = state.pe_other_pid; 30641.30Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 30651.29Skamil 30661.29Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 30671.61Skre "%d\n", TWAIT_FNAME, child2, child); 30681.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 30691.29Skamil child2); 30701.1Skamil 30711.29Skamil validate_status_stopped(status, SIGTRAP); 30721.1Skamil 30731.61Skre SYSCALL_REQUIRE( 30741.61Skre ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 30751.31Skamil if (trackfork && fn == fork) { 30761.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 30771.30Skamil PTRACE_FORK); 30781.30Skamil } 30791.31Skamil if (trackvfork && fn == vfork) { 30801.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 30811.30Skamil PTRACE_VFORK); 30821.30Skamil } 30831.30Skamil 30841.29Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 30851.29Skamil 30861.29Skamil DPRINTF("Before resuming the forkee process where it left off " 30871.29Skamil "and without signal to be sent\n"); 30881.61Skre SYSCALL_REQUIRE( 30891.61Skre ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 30901.29Skamil 30911.29Skamil DPRINTF("Before resuming the child process where it left off " 30921.61Skre "and without signal to be sent\n"); 30931.29Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 30941.30Skamil } 30951.30Skamil#endif 30961.30Skamil 30971.31Skamil if (trackvforkdone && fn == vfork) { 30981.30Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 30991.61Skre child); 31001.61Skre TWAIT_REQUIRE_SUCCESS( 31011.61Skre wpid = TWAIT_GENERIC(child, &status, 0), child); 31021.30Skamil 31031.30Skamil validate_status_stopped(status, SIGTRAP); 31041.30Skamil 31051.61Skre SYSCALL_REQUIRE( 31061.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 31071.30Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 31081.30Skamil 31091.30Skamil child2 = state.pe_other_pid; 31101.30Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 31111.61Skre child2); 31121.30Skamil 31131.30Skamil DPRINTF("Before resuming the child process where it left off " 31141.61Skre "and without signal to be sent\n"); 31151.30Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31161.30Skamil } 31171.29Skamil 31181.30Skamil#if defined(TWAIT_HAVE_PID) 31191.31Skamil if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) { 31201.29Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 31211.61Skre "\n", TWAIT_FNAME); 31221.61Skre TWAIT_REQUIRE_SUCCESS( 31231.61Skre wpid = TWAIT_GENERIC(child2, &status, 0), child2); 31241.29Skamil 31251.29Skamil validate_status_exited(status, exitval2); 31261.29Skamil 31271.29Skamil DPRINTF("Before calling %s() for the forkee - expected no " 31281.61Skre "process\n", TWAIT_FNAME); 31291.29Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 31301.29Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 31311.29Skamil } 31321.29Skamil#endif 31331.1Skamil 31341.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 31351.1Skamil "SIGCHLD\n", TWAIT_FNAME); 31361.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31371.1Skamil 31381.1Skamil validate_status_stopped(status, SIGCHLD); 31391.1Skamil 31401.13Schristos DPRINTF("Before resuming the child process where it left off and " 31411.1Skamil "without signal to be sent\n"); 31421.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31431.1Skamil 31441.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 31451.1Skamil TWAIT_FNAME); 31461.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31471.1Skamil 31481.1Skamil validate_status_exited(status, exitval); 31491.1Skamil 31501.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 31511.1Skamil TWAIT_FNAME); 31521.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 31531.1Skamil} 31541.28Skamil 31551.105Skamil#define FORK_TEST(name,fun,tfork,tvfork,tvforkdone) \ 31561.61SkreATF_TC(name); \ 31571.61SkreATF_TC_HEAD(name, tc) \ 31581.61Skre{ \ 31591.105Skamil atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) " \ 31601.105Skamil "called with 0%s%s%s in EVENT_MASK", \ 31611.105Skamil tfork ? "|PTRACE_FORK" : "", \ 31621.105Skamil tvfork ? "|PTRACE_VFORK" : "", \ 31631.105Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 31641.61Skre} \ 31651.61Skre \ 31661.61SkreATF_TC_BODY(name, tc) \ 31671.61Skre{ \ 31681.61Skre \ 31691.105Skamil fork_body(fun, tfork, tvfork, tvforkdone); \ 31701.32Skamil} 31711.32Skamil 31721.105SkamilFORK_TEST(fork1, fork, false, false, false) 31731.31Skamil#if defined(TWAIT_HAVE_PID) 31741.105SkamilFORK_TEST(fork2, fork, true, false, false) 31751.105SkamilFORK_TEST(fork3, fork, false, true, false) 31761.105SkamilFORK_TEST(fork4, fork, true, true, false) 31771.31Skamil#endif 31781.105SkamilFORK_TEST(fork5, fork, false, false, true) 31791.31Skamil#if defined(TWAIT_HAVE_PID) 31801.105SkamilFORK_TEST(fork6, fork, true, false, true) 31811.105SkamilFORK_TEST(fork7, fork, false, true, true) 31821.105SkamilFORK_TEST(fork8, fork, true, true, true) 31831.31Skamil#endif 31841.1Skamil 31851.110Skamil#if TEST_VFORK_ENABLED 31861.105SkamilFORK_TEST(vfork1, vfork, false, false, false) 31871.31Skamil#if defined(TWAIT_HAVE_PID) 31881.105SkamilFORK_TEST(vfork2, vfork, true, false, false) 31891.105SkamilFORK_TEST(vfork3, vfork, false, true, false) 31901.105SkamilFORK_TEST(vfork4, vfork, true, true, false) 31911.31Skamil#endif 31921.105SkamilFORK_TEST(vfork5, vfork, false, false, true) 31931.31Skamil#if defined(TWAIT_HAVE_PID) 31941.105SkamilFORK_TEST(vfork6, vfork, true, false, true) 31951.105SkamilFORK_TEST(vfork7, vfork, false, true, true) 31961.105SkamilFORK_TEST(vfork8, vfork, true, true, true) 31971.31Skamil#endif 31981.110Skamil#endif 31991.31Skamil 32001.54Skamil/// ---------------------------------------------------------------------------- 32011.31Skamil 32021.116Skamil#if defined(TWAIT_HAVE_PID) 32031.116Skamilstatic void 32041.116Skamilfork_detach_forker_body(bool detachfork, bool detachvfork, 32051.116Skamil bool detachvforkdone, bool kill_process) 32061.116Skamil{ 32071.116Skamil const int exitval = 5; 32081.116Skamil const int exitval2 = 15; 32091.116Skamil const int sigval = SIGSTOP; 32101.116Skamil pid_t child, child2 = 0, wpid; 32111.116Skamil#if defined(TWAIT_HAVE_STATUS) 32121.116Skamil int status; 32131.116Skamil#endif 32141.116Skamil ptrace_state_t state; 32151.116Skamil const int slen = sizeof(state); 32161.116Skamil ptrace_event_t event; 32171.116Skamil const int elen = sizeof(event); 32181.116Skamil 32191.116Skamil pid_t (*fn)(void); 32201.116Skamil int op; 32211.116Skamil 32221.116Skamil ATF_REQUIRE((detachfork && !detachvfork && !detachvforkdone) || 32231.116Skamil (!detachfork && detachvfork && !detachvforkdone) || 32241.116Skamil (!detachfork && !detachvfork && detachvforkdone)); 32251.116Skamil 32261.116Skamil if (detachfork) 32271.116Skamil fn = fork; 32281.116Skamil else 32291.116Skamil fn = vfork; 32301.116Skamil 32311.116Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 32321.116Skamil SYSCALL_REQUIRE((child = fork()) != -1); 32331.116Skamil if (child == 0) { 32341.116Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 32351.116Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 32361.116Skamil 32371.116Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 32381.116Skamil FORKEE_ASSERT(raise(sigval) == 0); 32391.116Skamil 32401.116Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 32411.116Skamil 32421.116Skamil if (child2 == 0) 32431.116Skamil _exit(exitval2); 32441.116Skamil 32451.116Skamil FORKEE_REQUIRE_SUCCESS 32461.116Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 32471.116Skamil 32481.116Skamil forkee_status_exited(status, exitval2); 32491.116Skamil 32501.116Skamil DPRINTF("Before exiting of the child process\n"); 32511.116Skamil _exit(exitval); 32521.116Skamil } 32531.116Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 32541.116Skamil 32551.116Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 32561.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 32571.116Skamil 32581.116Skamil validate_status_stopped(status, sigval); 32591.116Skamil 32601.116Skamil DPRINTF("Set EVENT_MASK for the child %d\n", child); 32611.116Skamil event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE; 32621.116Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 32631.116Skamil 32641.116Skamil DPRINTF("Before resuming the child process where it left off and " 32651.116Skamil "without signal to be sent\n"); 32661.116Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 32671.116Skamil 32681.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child); 32691.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 32701.116Skamil 32711.116Skamil validate_status_stopped(status, SIGTRAP); 32721.116Skamil 32731.116Skamil SYSCALL_REQUIRE( 32741.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 32751.116Skamil op = (fn == fork) ? PTRACE_FORK : PTRACE_VFORK; 32761.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 32771.116Skamil 32781.116Skamil child2 = state.pe_other_pid; 32791.116Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 32801.116Skamil 32811.116Skamil if (detachfork || detachvfork) 32821.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 32831.116Skamil else 32841.116Skamil op = PT_CONTINUE; 32851.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 32861.116Skamil 32871.116Skamil DPRINTF("Before calling %s() for the forkee %d of the child %d\n", 32881.116Skamil TWAIT_FNAME, child2, child); 32891.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 32901.116Skamil 32911.116Skamil validate_status_stopped(status, SIGTRAP); 32921.116Skamil 32931.116Skamil SYSCALL_REQUIRE( 32941.116Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 32951.116Skamil op = (fn == fork) ? PTRACE_FORK : PTRACE_VFORK; 32961.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 32971.116Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 32981.116Skamil 32991.116Skamil DPRINTF("Before resuming the forkee process where it left off " 33001.116Skamil "and without signal to be sent\n"); 33011.116Skamil SYSCALL_REQUIRE( 33021.116Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 33031.116Skamil 33041.116Skamil if (detachvforkdone && fn == vfork) { 33051.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 33061.116Skamil child); 33071.116Skamil TWAIT_REQUIRE_SUCCESS( 33081.116Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 33091.116Skamil 33101.116Skamil validate_status_stopped(status, SIGTRAP); 33111.116Skamil 33121.116Skamil SYSCALL_REQUIRE( 33131.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 33141.116Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 33151.116Skamil 33161.116Skamil child2 = state.pe_other_pid; 33171.116Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 33181.116Skamil child2); 33191.116Skamil 33201.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 33211.116Skamil DPRINTF("Before resuming the child process where it left off " 33221.116Skamil "and without signal to be sent\n"); 33231.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 33241.116Skamil } 33251.116Skamil 33261.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 33271.116Skamil TWAIT_FNAME); 33281.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 33291.116Skamil 33301.116Skamil validate_status_exited(status, exitval2); 33311.116Skamil 33321.116Skamil DPRINTF("Before calling %s() for the forkee - expected no process\n", 33331.116Skamil TWAIT_FNAME); 33341.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child2, &status, 0)); 33351.116Skamil 33361.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 33371.116Skamil TWAIT_FNAME); 33381.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33391.116Skamil 33401.116Skamil if (kill_process) { 33411.116Skamil validate_status_signaled(status, SIGKILL, 0); 33421.116Skamil } else { 33431.116Skamil validate_status_exited(status, exitval); 33441.116Skamil } 33451.116Skamil 33461.116Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 33471.116Skamil TWAIT_FNAME); 33481.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 33491.116Skamil} 33501.116Skamil 33511.116Skamil#define FORK_DETACH_FORKER(name,detfork,detvfork,detvforkdone,kprocess) \ 33521.116SkamilATF_TC(name); \ 33531.116SkamilATF_TC_HEAD(name, tc) \ 33541.116Skamil{ \ 33551.116Skamil atf_tc_set_md_var(tc, "descr", "Verify %s %s%s%s", \ 33561.116Skamil kprocess ? "killed" : "detached", \ 33571.116Skamil detfork ? "forker" : "", \ 33581.116Skamil detvfork ? "vforker" : "", \ 33591.116Skamil detvforkdone ? "vforker done" : ""); \ 33601.116Skamil} \ 33611.116Skamil \ 33621.116SkamilATF_TC_BODY(name, tc) \ 33631.116Skamil{ \ 33641.116Skamil \ 33651.116Skamil fork_detach_forker_body(detfork, detvfork, detvforkdone, \ 33661.116Skamil kprocess); \ 33671.116Skamil} 33681.116Skamil 33691.116SkamilFORK_DETACH_FORKER(fork_detach_forker, true, false, false, false) 33701.116Skamil#if TEST_VFORK_ENABLED 33711.116SkamilFORK_DETACH_FORKER(vfork_detach_vforker, false, true, false, false) 33721.116SkamilFORK_DETACH_FORKER(vfork_detach_vforkerdone, false, false, true, false) 33731.116Skamil#endif 33741.116SkamilFORK_DETACH_FORKER(fork_kill_forker, true, false, false, true) 33751.116Skamil#if TEST_VFORK_ENABLED 33761.116SkamilFORK_DETACH_FORKER(vfork_kill_vforker, false, true, false, true) 33771.116SkamilFORK_DETACH_FORKER(vfork_kill_vforkerdone, false, false, true, true) 33781.116Skamil#endif 33791.116Skamil#endif 33801.116Skamil 33811.116Skamil/// ---------------------------------------------------------------------------- 33821.116Skamil 33831.110Skamil#if TEST_VFORK_ENABLED 33841.108Skamilstatic void 33851.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void)) 33861.108Skamil{ 33871.108Skamil const int exitval = 5; 33881.108Skamil const int exitval2 = 15; 33891.108Skamil pid_t child, child2 = 0, wpid; 33901.108Skamil#if defined(TWAIT_HAVE_STATUS) 33911.108Skamil int status; 33921.108Skamil#endif 33931.108Skamil 33941.108Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 33951.108Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 33961.108Skamil if (child == 0) { 33971.108Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 33981.108Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 33991.108Skamil 34001.108Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 34011.108Skamil 34021.108Skamil if (child2 == 0) 34031.108Skamil _exit(exitval2); 34041.108Skamil 34051.108Skamil FORKEE_REQUIRE_SUCCESS 34061.108Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 34071.108Skamil 34081.108Skamil forkee_status_exited(status, exitval2); 34091.108Skamil 34101.108Skamil DPRINTF("Before exiting of the child process\n"); 34111.108Skamil _exit(exitval); 34121.108Skamil } 34131.108Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 34141.108Skamil 34151.108Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 34161.108Skamil TWAIT_FNAME); 34171.108Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 34181.108Skamil 34191.108Skamil validate_status_exited(status, exitval); 34201.108Skamil 34211.108Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 34221.108Skamil TWAIT_FNAME); 34231.108Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 34241.108Skamil} 34251.108Skamil 34261.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun) \ 34271.108SkamilATF_TC(name); \ 34281.108SkamilATF_TC_HEAD(name, tc) \ 34291.108Skamil{ \ 34301.108Skamil atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) " \ 34311.108Skamil "called from vfork(2)ed child"); \ 34321.108Skamil} \ 34331.108Skamil \ 34341.108SkamilATF_TC_BODY(name, tc) \ 34351.108Skamil{ \ 34361.108Skamil \ 34371.108Skamil traceme_vfork_fork_body(fun); \ 34381.108Skamil} 34391.108Skamil 34401.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork) 34411.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork) 34421.110Skamil#endif 34431.108Skamil 34441.108Skamil/// ---------------------------------------------------------------------------- 34451.108Skamil 34461.54Skamilenum bytes_transfer_type { 34471.54Skamil BYTES_TRANSFER_DATA, 34481.54Skamil BYTES_TRANSFER_DATAIO, 34491.54Skamil BYTES_TRANSFER_TEXT, 34501.54Skamil BYTES_TRANSFER_TEXTIO, 34511.54Skamil BYTES_TRANSFER_AUXV 34521.54Skamil}; 34531.31Skamil 34541.54Skamilstatic int __used 34551.54Skamilbytes_transfer_dummy(int a, int b, int c, int d) 34561.54Skamil{ 34571.54Skamil int e, f, g, h; 34581.1Skamil 34591.54Skamil a *= 4; 34601.54Skamil b += 3; 34611.54Skamil c -= 2; 34621.54Skamil d /= 1; 34631.1Skamil 34641.54Skamil e = strtol("10", NULL, 10); 34651.54Skamil f = strtol("20", NULL, 10); 34661.54Skamil g = strtol("30", NULL, 10); 34671.54Skamil h = strtol("40", NULL, 10); 34681.1Skamil 34691.54Skamil return (a + b * c - d) + (e * f - g / h); 34701.1Skamil} 34711.1Skamil 34721.54Skamilstatic void 34731.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type) 34741.1Skamil{ 34751.1Skamil const int exitval = 5; 34761.1Skamil const int sigval = SIGSTOP; 34771.1Skamil pid_t child, wpid; 34781.54Skamil bool skip = false; 34791.1Skamil 34801.54Skamil int lookup_me = 0; 34811.54Skamil uint8_t lookup_me8 = 0; 34821.54Skamil uint16_t lookup_me16 = 0; 34831.54Skamil uint32_t lookup_me32 = 0; 34841.54Skamil uint64_t lookup_me64 = 0; 34851.1Skamil 34861.54Skamil int magic = 0x13579246; 34871.54Skamil uint8_t magic8 = 0xab; 34881.54Skamil uint16_t magic16 = 0x1234; 34891.54Skamil uint32_t magic32 = 0x98765432; 34901.54Skamil uint64_t magic64 = 0xabcdef0123456789; 34911.1Skamil 34921.54Skamil struct ptrace_io_desc io; 34931.1Skamil#if defined(TWAIT_HAVE_STATUS) 34941.1Skamil int status; 34951.1Skamil#endif 34961.60Skre /* 513 is just enough, for the purposes of ATF it's good enough */ 34971.60Skre AuxInfo ai[513], *aip; 34981.55Schristos 34991.55Schristos ATF_REQUIRE(size < sizeof(ai)); 35001.1Skamil 35011.54Skamil /* Prepare variables for .TEXT transfers */ 35021.54Skamil switch (type) { 35031.54Skamil case BYTES_TRANSFER_TEXT: 35041.54Skamil memcpy(&magic, bytes_transfer_dummy, sizeof(magic)); 35051.54Skamil break; 35061.54Skamil case BYTES_TRANSFER_TEXTIO: 35071.54Skamil switch (size) { 35081.54Skamil case 8: 35091.54Skamil memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8)); 35101.54Skamil break; 35111.54Skamil case 16: 35121.54Skamil memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16)); 35131.54Skamil break; 35141.54Skamil case 32: 35151.54Skamil memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32)); 35161.54Skamil break; 35171.54Skamil case 64: 35181.54Skamil memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64)); 35191.54Skamil break; 35201.54Skamil } 35211.54Skamil break; 35221.54Skamil default: 35231.54Skamil break; 35241.54Skamil } 35251.1Skamil 35261.54Skamil /* Prepare variables for PIOD and AUXV transfers */ 35271.54Skamil switch (type) { 35281.54Skamil case BYTES_TRANSFER_TEXTIO: 35291.54Skamil case BYTES_TRANSFER_DATAIO: 35301.54Skamil io.piod_op = operation; 35311.54Skamil switch (size) { 35321.54Skamil case 8: 35331.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 35341.54Skamil (void *)bytes_transfer_dummy : 35351.54Skamil &lookup_me8; 35361.54Skamil io.piod_addr = &lookup_me8; 35371.54Skamil io.piod_len = sizeof(lookup_me8); 35381.54Skamil break; 35391.54Skamil case 16: 35401.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 35411.54Skamil (void *)bytes_transfer_dummy : 35421.54Skamil &lookup_me16; 35431.54Skamil io.piod_addr = &lookup_me16; 35441.54Skamil io.piod_len = sizeof(lookup_me16); 35451.54Skamil break; 35461.54Skamil case 32: 35471.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 35481.54Skamil (void *)bytes_transfer_dummy : 35491.54Skamil &lookup_me32; 35501.54Skamil io.piod_addr = &lookup_me32; 35511.54Skamil io.piod_len = sizeof(lookup_me32); 35521.54Skamil break; 35531.54Skamil case 64: 35541.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 35551.54Skamil (void *)bytes_transfer_dummy : 35561.54Skamil &lookup_me64; 35571.54Skamil io.piod_addr = &lookup_me64; 35581.54Skamil io.piod_len = sizeof(lookup_me64); 35591.54Skamil break; 35601.54Skamil default: 35611.54Skamil break; 35621.54Skamil } 35631.54Skamil break; 35641.54Skamil case BYTES_TRANSFER_AUXV: 35651.54Skamil io.piod_op = operation; 35661.54Skamil io.piod_offs = 0; 35671.54Skamil io.piod_addr = ai; 35681.54Skamil io.piod_len = size; 35691.54Skamil break; 35701.54Skamil default: 35711.54Skamil break; 35721.1Skamil } 35731.1Skamil 35741.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 35751.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 35761.1Skamil if (child == 0) { 35771.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 35781.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 35791.1Skamil 35801.54Skamil switch (type) { 35811.54Skamil case BYTES_TRANSFER_DATA: 35821.54Skamil switch (operation) { 35831.54Skamil case PT_READ_D: 35841.54Skamil case PT_READ_I: 35851.54Skamil lookup_me = magic; 35861.54Skamil break; 35871.54Skamil default: 35881.54Skamil break; 35891.54Skamil } 35901.54Skamil break; 35911.54Skamil case BYTES_TRANSFER_DATAIO: 35921.54Skamil switch (operation) { 35931.54Skamil case PIOD_READ_D: 35941.54Skamil case PIOD_READ_I: 35951.54Skamil switch (size) { 35961.54Skamil case 8: 35971.54Skamil lookup_me8 = magic8; 35981.54Skamil break; 35991.54Skamil case 16: 36001.54Skamil lookup_me16 = magic16; 36011.54Skamil break; 36021.54Skamil case 32: 36031.54Skamil lookup_me32 = magic32; 36041.54Skamil break; 36051.54Skamil case 64: 36061.54Skamil lookup_me64 = magic64; 36071.54Skamil break; 36081.54Skamil default: 36091.54Skamil break; 36101.54Skamil } 36111.54Skamil break; 36121.54Skamil default: 36131.54Skamil break; 36141.54Skamil } 36151.54Skamil default: 36161.54Skamil break; 36171.54Skamil } 36181.54Skamil 36191.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 36201.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 36211.1Skamil 36221.54Skamil /* Handle PIOD and PT separately as operation values overlap */ 36231.54Skamil switch (type) { 36241.54Skamil case BYTES_TRANSFER_DATA: 36251.54Skamil switch (operation) { 36261.54Skamil case PT_WRITE_D: 36271.54Skamil case PT_WRITE_I: 36281.54Skamil FORKEE_ASSERT_EQ(lookup_me, magic); 36291.54Skamil break; 36301.54Skamil default: 36311.54Skamil break; 36321.54Skamil } 36331.54Skamil break; 36341.54Skamil case BYTES_TRANSFER_DATAIO: 36351.54Skamil switch (operation) { 36361.54Skamil case PIOD_WRITE_D: 36371.54Skamil case PIOD_WRITE_I: 36381.54Skamil switch (size) { 36391.54Skamil case 8: 36401.54Skamil FORKEE_ASSERT_EQ(lookup_me8, magic8); 36411.54Skamil break; 36421.54Skamil case 16: 36431.54Skamil FORKEE_ASSERT_EQ(lookup_me16, magic16); 36441.54Skamil break; 36451.54Skamil case 32: 36461.54Skamil FORKEE_ASSERT_EQ(lookup_me32, magic32); 36471.54Skamil break; 36481.54Skamil case 64: 36491.54Skamil FORKEE_ASSERT_EQ(lookup_me64, magic64); 36501.54Skamil break; 36511.54Skamil default: 36521.54Skamil break; 36531.54Skamil } 36541.54Skamil break; 36551.54Skamil default: 36561.54Skamil break; 36571.54Skamil } 36581.54Skamil break; 36591.54Skamil case BYTES_TRANSFER_TEXT: 36601.54Skamil FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy, 36611.54Skamil sizeof(magic)) == 0); 36621.54Skamil break; 36631.54Skamil case BYTES_TRANSFER_TEXTIO: 36641.54Skamil switch (size) { 36651.54Skamil case 8: 36661.54Skamil FORKEE_ASSERT(memcmp(&magic8, 36671.54Skamil bytes_transfer_dummy, 36681.54Skamil sizeof(magic8)) == 0); 36691.54Skamil break; 36701.54Skamil case 16: 36711.54Skamil FORKEE_ASSERT(memcmp(&magic16, 36721.54Skamil bytes_transfer_dummy, 36731.54Skamil sizeof(magic16)) == 0); 36741.54Skamil break; 36751.54Skamil case 32: 36761.54Skamil FORKEE_ASSERT(memcmp(&magic32, 36771.54Skamil bytes_transfer_dummy, 36781.54Skamil sizeof(magic32)) == 0); 36791.54Skamil break; 36801.54Skamil case 64: 36811.54Skamil FORKEE_ASSERT(memcmp(&magic64, 36821.54Skamil bytes_transfer_dummy, 36831.54Skamil sizeof(magic64)) == 0); 36841.54Skamil break; 36851.54Skamil } 36861.54Skamil break; 36871.54Skamil default: 36881.54Skamil break; 36891.54Skamil } 36901.54Skamil 36911.13Schristos DPRINTF("Before exiting of the child process\n"); 36921.1Skamil _exit(exitval); 36931.1Skamil } 36941.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 36951.1Skamil 36961.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 36971.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 36981.1Skamil 36991.1Skamil validate_status_stopped(status, sigval); 37001.1Skamil 37011.54Skamil /* Check PaX MPROTECT */ 37021.54Skamil if (!can_we_write_to_text(child)) { 37031.54Skamil switch (type) { 37041.54Skamil case BYTES_TRANSFER_TEXTIO: 37051.54Skamil switch (operation) { 37061.54Skamil case PIOD_WRITE_D: 37071.54Skamil case PIOD_WRITE_I: 37081.54Skamil skip = true; 37091.54Skamil break; 37101.54Skamil default: 37111.54Skamil break; 37121.54Skamil } 37131.54Skamil break; 37141.54Skamil case BYTES_TRANSFER_TEXT: 37151.54Skamil switch (operation) { 37161.54Skamil case PT_WRITE_D: 37171.54Skamil case PT_WRITE_I: 37181.54Skamil skip = true; 37191.54Skamil break; 37201.54Skamil default: 37211.54Skamil break; 37221.54Skamil } 37231.54Skamil break; 37241.54Skamil default: 37251.54Skamil break; 37261.54Skamil } 37271.54Skamil } 37281.1Skamil 37291.54Skamil /* Bailout cleanly killing the child process */ 37301.54Skamil if (skip) { 37311.54Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1); 37321.54Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 37331.54Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 37341.54Skamil child); 37351.1Skamil 37361.54Skamil validate_status_signaled(status, SIGKILL, 0); 37371.1Skamil 37381.54Skamil atf_tc_skip("PaX MPROTECT setup prevents writes to .text"); 37391.54Skamil } 37401.1Skamil 37411.54Skamil DPRINTF("Calling operation to transfer bytes between child=%d and " 37421.54Skamil "parent=%d\n", child, getpid()); 37431.1Skamil 37441.54Skamil switch (type) { 37451.54Skamil case BYTES_TRANSFER_TEXTIO: 37461.54Skamil case BYTES_TRANSFER_DATAIO: 37471.54Skamil case BYTES_TRANSFER_AUXV: 37481.54Skamil switch (operation) { 37491.54Skamil case PIOD_WRITE_D: 37501.54Skamil case PIOD_WRITE_I: 37511.54Skamil switch (size) { 37521.54Skamil case 8: 37531.54Skamil lookup_me8 = magic8; 37541.54Skamil break; 37551.54Skamil case 16: 37561.54Skamil lookup_me16 = magic16; 37571.54Skamil break; 37581.54Skamil case 32: 37591.54Skamil lookup_me32 = magic32; 37601.54Skamil break; 37611.54Skamil case 64: 37621.54Skamil lookup_me64 = magic64; 37631.54Skamil break; 37641.54Skamil default: 37651.54Skamil break; 37661.54Skamil } 37671.54Skamil break; 37681.54Skamil default: 37691.54Skamil break; 37701.54Skamil } 37711.54Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); 37721.54Skamil switch (operation) { 37731.54Skamil case PIOD_READ_D: 37741.54Skamil case PIOD_READ_I: 37751.54Skamil switch (size) { 37761.54Skamil case 8: 37771.54Skamil ATF_REQUIRE_EQ(lookup_me8, magic8); 37781.54Skamil break; 37791.54Skamil case 16: 37801.54Skamil ATF_REQUIRE_EQ(lookup_me16, magic16); 37811.54Skamil break; 37821.54Skamil case 32: 37831.54Skamil ATF_REQUIRE_EQ(lookup_me32, magic32); 37841.54Skamil break; 37851.54Skamil case 64: 37861.54Skamil ATF_REQUIRE_EQ(lookup_me64, magic64); 37871.54Skamil break; 37881.54Skamil default: 37891.54Skamil break; 37901.54Skamil } 37911.54Skamil break; 37921.54Skamil case PIOD_READ_AUXV: 37931.54Skamil DPRINTF("Asserting that AUXV length (%zu) is > 0\n", 37941.54Skamil io.piod_len); 37951.54Skamil ATF_REQUIRE(io.piod_len > 0); 37961.54Skamil for (aip = ai; aip->a_type != AT_NULL; aip++) 37971.54Skamil DPRINTF("a_type=%#llx a_v=%#llx\n", 37981.54Skamil (long long int)aip->a_type, 37991.54Skamil (long long int)aip->a_v); 38001.54Skamil break; 38011.54Skamil default: 38021.54Skamil break; 38031.54Skamil } 38041.54Skamil break; 38051.54Skamil case BYTES_TRANSFER_TEXT: 38061.54Skamil switch (operation) { 38071.54Skamil case PT_READ_D: 38081.54Skamil case PT_READ_I: 38091.54Skamil errno = 0; 38101.54Skamil lookup_me = ptrace(operation, child, 38111.54Skamil bytes_transfer_dummy, 0); 38121.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 38131.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 38141.54Skamil break; 38151.54Skamil case PT_WRITE_D: 38161.54Skamil case PT_WRITE_I: 38171.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, 38181.54Skamil bytes_transfer_dummy, magic) 38191.54Skamil != -1); 38201.54Skamil break; 38211.54Skamil default: 38221.54Skamil break; 38231.54Skamil } 38241.54Skamil break; 38251.54Skamil case BYTES_TRANSFER_DATA: 38261.54Skamil switch (operation) { 38271.54Skamil case PT_READ_D: 38281.54Skamil case PT_READ_I: 38291.54Skamil errno = 0; 38301.54Skamil lookup_me = ptrace(operation, child, &lookup_me, 0); 38311.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 38321.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 38331.54Skamil break; 38341.54Skamil case PT_WRITE_D: 38351.54Skamil case PT_WRITE_I: 38361.54Skamil lookup_me = magic; 38371.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me, 38381.54Skamil magic) != -1); 38391.54Skamil break; 38401.54Skamil default: 38411.54Skamil break; 38421.54Skamil } 38431.54Skamil break; 38441.54Skamil default: 38451.54Skamil break; 38461.54Skamil } 38471.1Skamil 38481.13Schristos DPRINTF("Before resuming the child process where it left off and " 38491.1Skamil "without signal to be sent\n"); 38501.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 38511.1Skamil 38521.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38531.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 38541.1Skamil 38551.1Skamil validate_status_exited(status, exitval); 38561.1Skamil 38571.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38581.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 38591.1Skamil} 38601.1Skamil 38611.61Skre#define BYTES_TRANSFER(test, operation, size, type) \ 38621.61SkreATF_TC(test); \ 38631.61SkreATF_TC_HEAD(test, tc) \ 38641.61Skre{ \ 38651.61Skre atf_tc_set_md_var(tc, "descr", \ 38661.61Skre "Verify bytes transfer operation" #operation " and size " #size \ 38671.61Skre " of type " #type); \ 38681.61Skre} \ 38691.61Skre \ 38701.61SkreATF_TC_BODY(test, tc) \ 38711.61Skre{ \ 38721.61Skre \ 38731.61Skre bytes_transfer(operation, size, BYTES_TRANSFER_##type); \ 38741.1Skamil} 38751.1Skamil 38761.54Skamil// DATA 38771.1Skamil 38781.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO) 38791.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO) 38801.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO) 38811.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO) 38821.54Skamil 38831.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO) 38841.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO) 38851.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO) 38861.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO) 38871.54Skamil 38881.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO) 38891.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO) 38901.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO) 38911.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO) 38921.54Skamil 38931.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO) 38941.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO) 38951.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO) 38961.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO) 38971.54Skamil 38981.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA) 38991.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA) 39001.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA) 39011.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA) 39021.54Skamil 39031.54Skamil// TEXT 39041.54Skamil 39051.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO) 39061.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO) 39071.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO) 39081.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO) 39091.54Skamil 39101.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO) 39111.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO) 39121.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO) 39131.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO) 39141.54Skamil 39151.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO) 39161.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO) 39171.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO) 39181.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO) 39191.54Skamil 39201.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO) 39211.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO) 39221.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO) 39231.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO) 39241.54Skamil 39251.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT) 39261.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT) 39271.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT) 39281.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT) 39291.1Skamil 39301.54Skamil// AUXV 39311.1Skamil 39321.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV) 39331.1Skamil 39341.54Skamil/// ---------------------------------------------------------------------------- 39351.1Skamil 39361.101Skamilstatic void 39371.101Skamilbytes_transfer_alignment(const char *operation) 39381.101Skamil{ 39391.101Skamil const int exitval = 5; 39401.101Skamil const int sigval = SIGSTOP; 39411.101Skamil pid_t child, wpid; 39421.101Skamil#if defined(TWAIT_HAVE_STATUS) 39431.101Skamil int status; 39441.101Skamil#endif 39451.101Skamil char *buffer; 39461.101Skamil int vector; 39471.101Skamil size_t len; 39481.101Skamil size_t i; 39491.101Skamil int op; 39501.101Skamil 39511.101Skamil struct ptrace_io_desc io; 39521.101Skamil struct ptrace_siginfo info; 39531.101Skamil 39541.101Skamil memset(&io, 0, sizeof(io)); 39551.101Skamil memset(&info, 0, sizeof(info)); 39561.101Skamil 39571.101Skamil /* Testing misaligned byte transfer crossing page boundaries */ 39581.101Skamil len = sysconf(_SC_PAGESIZE) * 2; 39591.101Skamil buffer = malloc(len); 39601.101Skamil ATF_REQUIRE(buffer != NULL); 39611.101Skamil 39621.101Skamil /* Initialize the buffer with random data */ 39631.101Skamil for (i = 0; i < len; i++) 39641.101Skamil buffer[i] = i & 0xff; 39651.101Skamil 39661.101Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 39671.101Skamil SYSCALL_REQUIRE((child = fork()) != -1); 39681.101Skamil if (child == 0) { 39691.101Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 39701.101Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 39711.101Skamil 39721.101Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 39731.101Skamil FORKEE_ASSERT(raise(sigval) == 0); 39741.101Skamil 39751.101Skamil DPRINTF("Before exiting of the child process\n"); 39761.101Skamil _exit(exitval); 39771.101Skamil } 39781.101Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 39791.101Skamil 39801.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39811.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 39821.101Skamil 39831.101Skamil validate_status_stopped(status, sigval); 39841.101Skamil 39851.101Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 39861.101Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 39871.101Skamil != -1); 39881.101Skamil 39891.101Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 39901.101Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 39911.101Skamil "si_errno=%#x\n", 39921.101Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 39931.101Skamil info.psi_siginfo.si_errno); 39941.101Skamil 39951.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 39961.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 39971.101Skamil 39981.101Skamil if (strcmp(operation, "PT_READ_I") == 0 || 39991.101Skamil strcmp(operation, "PT_READ_D") == 0) { 40001.101Skamil if (strcmp(operation, "PT_READ_I")) 40011.101Skamil op = PT_READ_I; 40021.101Skamil else 40031.101Skamil op = PT_READ_D; 40041.101Skamil 40051.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 40061.101Skamil errno = 0; 40071.101Skamil vector = ptrace(op, child, buffer + i, 0); 40081.101Skamil ATF_REQUIRE_EQ(errno, 0); 40091.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 40101.101Skamil } 40111.101Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 40121.101Skamil strcmp(operation, "PT_WRITE_D") == 0) { 40131.101Skamil if (strcmp(operation, "PT_WRITE_I")) 40141.101Skamil op = PT_WRITE_I; 40151.101Skamil else 40161.101Skamil op = PT_WRITE_D; 40171.101Skamil 40181.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 40191.101Skamil memcpy(&vector, buffer + i, sizeof(int)); 40201.101Skamil SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector) 40211.101Skamil != -1); 40221.101Skamil } 40231.101Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 40241.101Skamil strcmp(operation, "PIOD_READ_D") == 0) { 40251.101Skamil if (strcmp(operation, "PIOD_READ_I")) 40261.101Skamil op = PIOD_READ_I; 40271.101Skamil else 40281.101Skamil op = PIOD_READ_D; 40291.101Skamil 40301.101Skamil io.piod_op = op; 40311.101Skamil io.piod_addr = &vector; 40321.101Skamil io.piod_len = sizeof(int); 40331.101Skamil 40341.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 40351.101Skamil io.piod_offs = buffer + i; 40361.101Skamil 40371.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 40381.101Skamil != -1); 40391.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 40401.101Skamil } 40411.101Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 40421.101Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 40431.101Skamil if (strcmp(operation, "PIOD_WRITE_I")) 40441.101Skamil op = PIOD_WRITE_I; 40451.101Skamil else 40461.101Skamil op = PIOD_WRITE_D; 40471.101Skamil 40481.101Skamil io.piod_op = op; 40491.101Skamil io.piod_addr = &vector; 40501.101Skamil io.piod_len = sizeof(int); 40511.101Skamil 40521.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 40531.101Skamil io.piod_offs = buffer + i; 40541.101Skamil 40551.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 40561.101Skamil != -1); 40571.101Skamil } 40581.101Skamil } else if (strcmp(operation, "PIOD_READ_AUXV") == 0) { 40591.101Skamil io.piod_op = PIOD_READ_AUXV; 40601.101Skamil io.piod_addr = &vector; 40611.101Skamil io.piod_len = sizeof(int); 40621.101Skamil 40631.101Skamil errno = 0; 40641.101Skamil i = 0; 40651.101Skamil /* Read the whole AUXV vector, it has no clear length */ 40661.101Skamil while (errno != EIO) { 40671.101Skamil io.piod_offs = (void *)(intptr_t)i; 40681.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 40691.101Skamil != -1 || (errno == EIO && i > 0)); 40701.101Skamil ++i; 40711.101Skamil } 40721.101Skamil } 40731.101Skamil 40741.101Skamil DPRINTF("Before resuming the child process where it left off " 40751.101Skamil "and without signal to be sent\n"); 40761.101Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 40771.101Skamil 40781.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 40791.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 40801.101Skamil child); 40811.101Skamil 40821.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 40831.101Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 40841.101Skamil} 40851.101Skamil 40861.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation) \ 40871.101SkamilATF_TC(test); \ 40881.101SkamilATF_TC_HEAD(test, tc) \ 40891.101Skamil{ \ 40901.101Skamil atf_tc_set_md_var(tc, "descr", \ 40911.101Skamil "Verify bytes transfer for potentially misaligned " \ 40921.101Skamil "operation " operation); \ 40931.101Skamil} \ 40941.101Skamil \ 40951.101SkamilATF_TC_BODY(test, tc) \ 40961.101Skamil{ \ 40971.101Skamil \ 40981.101Skamil bytes_transfer_alignment(operation); \ 40991.101Skamil} 41001.101Skamil 41011.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I") 41021.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D") 41031.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I") 41041.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D") 41051.101Skamil 41061.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I") 41071.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D") 41081.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I") 41091.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D") 41101.101Skamil 41111.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV") 41121.101Skamil 41131.101Skamil/// ---------------------------------------------------------------------------- 41141.101Skamil 41151.115Skamilstatic void 41161.115Skamilbytes_transfer_eof(const char *operation) 41171.115Skamil{ 41181.115Skamil const int exitval = 5; 41191.115Skamil const int sigval = SIGSTOP; 41201.115Skamil pid_t child, wpid; 41211.115Skamil#if defined(TWAIT_HAVE_STATUS) 41221.115Skamil int status; 41231.115Skamil#endif 41241.115Skamil FILE *fp; 41251.115Skamil char *p; 41261.115Skamil int vector; 41271.115Skamil int op; 41281.115Skamil 41291.115Skamil struct ptrace_io_desc io; 41301.115Skamil struct ptrace_siginfo info; 41311.115Skamil 41321.115Skamil memset(&io, 0, sizeof(io)); 41331.115Skamil memset(&info, 0, sizeof(info)); 41341.115Skamil 41351.115Skamil vector = 0; 41361.115Skamil 41371.115Skamil fp = tmpfile(); 41381.115Skamil ATF_REQUIRE(fp != NULL); 41391.115Skamil 41401.115Skamil p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0); 41411.115Skamil ATF_REQUIRE(p != MAP_FAILED); 41421.115Skamil 41431.115Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 41441.115Skamil SYSCALL_REQUIRE((child = fork()) != -1); 41451.115Skamil if (child == 0) { 41461.115Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 41471.115Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 41481.115Skamil 41491.115Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 41501.115Skamil FORKEE_ASSERT(raise(sigval) == 0); 41511.115Skamil 41521.115Skamil DPRINTF("Before exiting of the child process\n"); 41531.115Skamil _exit(exitval); 41541.115Skamil } 41551.115Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 41561.115Skamil 41571.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41581.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 41591.115Skamil 41601.115Skamil validate_status_stopped(status, sigval); 41611.115Skamil 41621.115Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 41631.115Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 41641.115Skamil != -1); 41651.115Skamil 41661.115Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 41671.115Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 41681.115Skamil "si_errno=%#x\n", 41691.115Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 41701.115Skamil info.psi_siginfo.si_errno); 41711.115Skamil 41721.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 41731.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 41741.115Skamil 41751.115Skamil if (strcmp(operation, "PT_READ_I") == 0 || 41761.115Skamil strcmp(operation, "PT_READ_D") == 0) { 41771.115Skamil if (strcmp(operation, "PT_READ_I")) 41781.115Skamil op = PT_READ_I; 41791.115Skamil else 41801.115Skamil op = PT_READ_D; 41811.115Skamil 41821.115Skamil errno = 0; 41831.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, 0) == -1); 41841.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 41851.115Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 41861.115Skamil strcmp(operation, "PT_WRITE_D") == 0) { 41871.115Skamil if (strcmp(operation, "PT_WRITE_I")) 41881.115Skamil op = PT_WRITE_I; 41891.115Skamil else 41901.115Skamil op = PT_WRITE_D; 41911.115Skamil 41921.115Skamil errno = 0; 41931.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, vector) == -1); 41941.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 41951.115Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 41961.115Skamil strcmp(operation, "PIOD_READ_D") == 0) { 41971.115Skamil if (strcmp(operation, "PIOD_READ_I")) 41981.115Skamil op = PIOD_READ_I; 41991.115Skamil else 42001.115Skamil op = PIOD_READ_D; 42011.115Skamil 42021.115Skamil io.piod_op = op; 42031.115Skamil io.piod_addr = &vector; 42041.115Skamil io.piod_len = sizeof(int); 42051.115Skamil io.piod_offs = p; 42061.115Skamil 42071.115Skamil errno = 0; 42081.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 42091.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 42101.115Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 42111.115Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 42121.115Skamil if (strcmp(operation, "PIOD_WRITE_I")) 42131.115Skamil op = PIOD_WRITE_I; 42141.115Skamil else 42151.115Skamil op = PIOD_WRITE_D; 42161.115Skamil 42171.115Skamil io.piod_op = op; 42181.115Skamil io.piod_addr = &vector; 42191.115Skamil io.piod_len = sizeof(int); 42201.115Skamil io.piod_offs = p; 42211.115Skamil 42221.115Skamil errno = 0; 42231.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 42241.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 42251.115Skamil } 42261.115Skamil 42271.115Skamil DPRINTF("Before resuming the child process where it left off " 42281.115Skamil "and without signal to be sent\n"); 42291.115Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 42301.115Skamil 42311.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 42321.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 42331.115Skamil child); 42341.115Skamil 42351.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 42361.115Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 42371.115Skamil} 42381.115Skamil 42391.115Skamil#define BYTES_TRANSFER_EOF(test, operation) \ 42401.115SkamilATF_TC(test); \ 42411.115SkamilATF_TC_HEAD(test, tc) \ 42421.115Skamil{ \ 42431.115Skamil atf_tc_set_md_var(tc, "descr", \ 42441.115Skamil "Verify bytes EOF byte transfer for the " operation \ 42451.115Skamil " operation"); \ 42461.115Skamil} \ 42471.115Skamil \ 42481.115SkamilATF_TC_BODY(test, tc) \ 42491.115Skamil{ \ 42501.115Skamil \ 42511.115Skamil bytes_transfer_eof(operation); \ 42521.115Skamil} 42531.115Skamil 42541.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_i, "PT_READ_I") 42551.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_d, "PT_READ_D") 42561.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_i, "PT_WRITE_I") 42571.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_d, "PT_WRITE_D") 42581.115Skamil 42591.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_i, "PIOD_READ_I") 42601.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_d, "PIOD_READ_D") 42611.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_i, "PIOD_WRITE_I") 42621.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_d, "PIOD_WRITE_D") 42631.115Skamil 42641.115Skamil/// ---------------------------------------------------------------------------- 42651.115Skamil 42661.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS) 42671.72Skamilstatic void 42681.72Skamilaccess_regs(const char *regset, const char *aux) 42691.1Skamil{ 42701.1Skamil const int exitval = 5; 42711.1Skamil const int sigval = SIGSTOP; 42721.1Skamil pid_t child, wpid; 42731.1Skamil#if defined(TWAIT_HAVE_STATUS) 42741.1Skamil int status; 42751.1Skamil#endif 42761.72Skamil#if defined(HAVE_GPREGS) 42771.72Skamil struct reg gpr; 42781.76Sscole register_t rgstr; 42791.1Skamil#endif 42801.72Skamil#if defined(HAVE_FPREGS) 42811.72Skamil struct fpreg fpr; 42821.1Skamil#endif 42831.76Sscole 42841.72Skamil#if !defined(HAVE_GPREGS) 42851.72Skamil if (strcmp(regset, "regs") == 0) 42861.72Skamil atf_tc_fail("Impossible test scenario!"); 42871.1Skamil#endif 42881.1Skamil 42891.72Skamil#if !defined(HAVE_FPREGS) 42901.72Skamil if (strcmp(regset, "fpregs") == 0) 42911.72Skamil atf_tc_fail("Impossible test scenario!"); 42921.1Skamil#endif 42931.1Skamil 42941.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 42951.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 42961.1Skamil if (child == 0) { 42971.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 42981.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 42991.1Skamil 43001.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 43011.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 43021.1Skamil 43031.13Schristos DPRINTF("Before exiting of the child process\n"); 43041.1Skamil _exit(exitval); 43051.1Skamil } 43061.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 43071.1Skamil 43081.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43091.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 43101.1Skamil 43111.1Skamil validate_status_stopped(status, sigval); 43121.1Skamil 43131.1Skamil#if defined(HAVE_GPREGS) 43141.72Skamil if (strcmp(regset, "regs") == 0) { 43151.72Skamil DPRINTF("Call GETREGS for the child process\n"); 43161.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1); 43171.72Skamil 43181.72Skamil if (strcmp(aux, "none") == 0) { 43191.72Skamil DPRINTF("Retrieved registers\n"); 43201.72Skamil } else if (strcmp(aux, "pc") == 0) { 43211.72Skamil rgstr = PTRACE_REG_PC(&gpr); 43221.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 43231.72Skamil } else if (strcmp(aux, "set_pc") == 0) { 43241.72Skamil rgstr = PTRACE_REG_PC(&gpr); 43251.72Skamil PTRACE_REG_SET_PC(&gpr, rgstr); 43261.72Skamil } else if (strcmp(aux, "sp") == 0) { 43271.72Skamil rgstr = PTRACE_REG_SP(&gpr); 43281.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 43291.72Skamil } else if (strcmp(aux, "intrv") == 0) { 43301.72Skamil rgstr = PTRACE_REG_INTRV(&gpr); 43311.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 43321.72Skamil } else if (strcmp(aux, "setregs") == 0) { 43331.72Skamil DPRINTF("Call SETREGS for the child process\n"); 43341.72Skamil SYSCALL_REQUIRE( 43351.72Skamil ptrace(PT_GETREGS, child, &gpr, 0) != -1); 43361.72Skamil } 43371.72Skamil } 43381.1Skamil#endif 43391.1Skamil 43401.72Skamil#if defined(HAVE_FPREGS) 43411.72Skamil if (strcmp(regset, "fpregs") == 0) { 43421.72Skamil DPRINTF("Call GETFPREGS for the child process\n"); 43431.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1); 43441.72Skamil 43451.72Skamil if (strcmp(aux, "getfpregs") == 0) { 43461.72Skamil DPRINTF("Retrieved FP registers\n"); 43471.72Skamil } else if (strcmp(aux, "setfpregs") == 0) { 43481.72Skamil DPRINTF("Call SETFPREGS for the child\n"); 43491.72Skamil SYSCALL_REQUIRE( 43501.72Skamil ptrace(PT_SETFPREGS, child, &fpr, 0) != -1); 43511.72Skamil } 43521.1Skamil } 43531.1Skamil#endif 43541.1Skamil 43551.13Schristos DPRINTF("Before resuming the child process where it left off and " 43561.1Skamil "without signal to be sent\n"); 43571.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 43581.1Skamil 43591.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43601.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 43611.1Skamil 43621.1Skamil validate_status_exited(status, exitval); 43631.1Skamil 43641.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43651.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 43661.1Skamil} 43671.1Skamil 43681.72Skamil#define ACCESS_REGS(test, regset, aux) \ 43691.72SkamilATF_TC(test); \ 43701.72SkamilATF_TC_HEAD(test, tc) \ 43711.72Skamil{ \ 43721.72Skamil atf_tc_set_md_var(tc, "descr", \ 43731.72Skamil "Verify " regset " with auxiliary operation: " aux); \ 43741.72Skamil} \ 43751.72Skamil \ 43761.72SkamilATF_TC_BODY(test, tc) \ 43771.72Skamil{ \ 43781.72Skamil \ 43791.72Skamil access_regs(regset, aux); \ 43801.1Skamil} 43811.1Skamil#endif 43821.1Skamil 43831.72Skamil#if defined(HAVE_GPREGS) 43841.72SkamilACCESS_REGS(access_regs1, "regs", "none") 43851.72SkamilACCESS_REGS(access_regs2, "regs", "pc") 43861.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc") 43871.72SkamilACCESS_REGS(access_regs4, "regs", "sp") 43881.72SkamilACCESS_REGS(access_regs5, "regs", "intrv") 43891.72SkamilACCESS_REGS(access_regs6, "regs", "setregs") 43901.1Skamil#endif 43911.1Skamil#if defined(HAVE_FPREGS) 43921.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs") 43931.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs") 43941.1Skamil#endif 43951.1Skamil 43961.72Skamil/// ---------------------------------------------------------------------------- 43971.1Skamil 43981.1Skamil#if defined(PT_STEP) 43991.1Skamilstatic void 44001.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored) 44011.1Skamil{ 44021.1Skamil const int exitval = 5; 44031.1Skamil const int sigval = SIGSTOP; 44041.1Skamil pid_t child, wpid; 44051.1Skamil#if defined(TWAIT_HAVE_STATUS) 44061.1Skamil int status; 44071.1Skamil#endif 44081.1Skamil int happy; 44091.95Skamil struct sigaction sa; 44101.81Skamil struct ptrace_siginfo info; 44111.95Skamil sigset_t intmask; 44121.95Skamil struct kinfo_proc2 kp; 44131.95Skamil size_t len = sizeof(kp); 44141.95Skamil 44151.95Skamil int name[6]; 44161.95Skamil const size_t namelen = __arraycount(name); 44171.95Skamil ki_sigset_t kp_sigmask; 44181.95Skamil ki_sigset_t kp_sigignore; 44191.1Skamil 44201.1Skamil#if defined(__arm__) 44211.1Skamil /* PT_STEP not supported on arm 32-bit */ 44221.1Skamil atf_tc_expect_fail("PR kern/52119"); 44231.1Skamil#endif 44241.1Skamil 44251.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 44261.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 44271.1Skamil if (child == 0) { 44281.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 44291.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 44301.1Skamil 44311.95Skamil if (masked) { 44321.95Skamil sigemptyset(&intmask); 44331.95Skamil sigaddset(&intmask, SIGTRAP); 44341.95Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 44351.95Skamil } 44361.95Skamil 44371.95Skamil if (ignored) { 44381.95Skamil memset(&sa, 0, sizeof(sa)); 44391.95Skamil sa.sa_handler = SIG_IGN; 44401.95Skamil sigemptyset(&sa.sa_mask); 44411.95Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 44421.95Skamil } 44431.95Skamil 44441.1Skamil happy = check_happy(999); 44451.1Skamil 44461.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 44471.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 44481.1Skamil 44491.1Skamil FORKEE_ASSERT_EQ(happy, check_happy(999)); 44501.1Skamil 44511.13Schristos DPRINTF("Before exiting of the child process\n"); 44521.1Skamil _exit(exitval); 44531.1Skamil } 44541.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 44551.1Skamil 44561.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44571.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44581.1Skamil 44591.1Skamil validate_status_stopped(status, sigval); 44601.1Skamil 44611.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 44621.81Skamil SYSCALL_REQUIRE( 44631.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 44641.81Skamil 44651.81Skamil DPRINTF("Before checking siginfo_t\n"); 44661.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 44671.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 44681.81Skamil 44691.95Skamil name[0] = CTL_KERN, 44701.95Skamil name[1] = KERN_PROC2, 44711.95Skamil name[2] = KERN_PROC_PID; 44721.95Skamil name[3] = child; 44731.95Skamil name[4] = sizeof(kp); 44741.95Skamil name[5] = 1; 44751.95Skamil 44761.95Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 44771.95Skamil 44781.95Skamil if (masked) 44791.95Skamil kp_sigmask = kp.p_sigmask; 44801.95Skamil 44811.95Skamil if (ignored) 44821.95Skamil kp_sigignore = kp.p_sigignore; 44831.95Skamil 44841.1Skamil while (N --> 0) { 44851.2Skamil if (setstep) { 44861.13Schristos DPRINTF("Before resuming the child process where it " 44871.2Skamil "left off and without signal to be sent (use " 44881.9Skamil "PT_SETSTEP and PT_CONTINUE)\n"); 44891.13Schristos SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1); 44901.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) 44911.2Skamil != -1); 44921.2Skamil } else { 44931.13Schristos DPRINTF("Before resuming the child process where it " 44941.2Skamil "left off and without signal to be sent (use " 44951.2Skamil "PT_STEP)\n"); 44961.13Schristos SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) 44971.2Skamil != -1); 44981.2Skamil } 44991.1Skamil 45001.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45011.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 45021.1Skamil child); 45031.1Skamil 45041.1Skamil validate_status_stopped(status, SIGTRAP); 45051.2Skamil 45061.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 45071.81Skamil SYSCALL_REQUIRE( 45081.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 45091.81Skamil 45101.81Skamil DPRINTF("Before checking siginfo_t\n"); 45111.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 45121.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE); 45131.81Skamil 45141.2Skamil if (setstep) { 45151.13Schristos SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1); 45161.2Skamil } 45171.95Skamil 45181.95Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 45191.95Skamil 45201.95Skamil if (masked) { 45211.95Skamil DPRINTF("kp_sigmask=" 45221.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 45231.95Skamil PRIx32 "\n", 45241.95Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 45251.95Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 45261.95Skamil 45271.95Skamil DPRINTF("kp.p_sigmask=" 45281.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 45291.95Skamil PRIx32 "\n", 45301.95Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 45311.95Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 45321.95Skamil 45331.95Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 45341.95Skamil sizeof(kp_sigmask))); 45351.95Skamil } 45361.95Skamil 45371.95Skamil if (ignored) { 45381.95Skamil DPRINTF("kp_sigignore=" 45391.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 45401.95Skamil PRIx32 "\n", 45411.95Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 45421.95Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 45431.95Skamil 45441.95Skamil DPRINTF("kp.p_sigignore=" 45451.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 45461.95Skamil PRIx32 "\n", 45471.95Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 45481.95Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 45491.95Skamil 45501.95Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 45511.95Skamil sizeof(kp_sigignore))); 45521.95Skamil } 45531.1Skamil } 45541.1Skamil 45551.13Schristos DPRINTF("Before resuming the child process where it left off and " 45561.1Skamil "without signal to be sent\n"); 45571.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 45581.1Skamil 45591.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45601.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 45611.1Skamil 45621.1Skamil validate_status_exited(status, exitval); 45631.1Skamil 45641.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45651.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 45661.1Skamil} 45671.1Skamil 45681.73Skamil#define PTRACE_STEP(test, N, setstep) \ 45691.73SkamilATF_TC(test); \ 45701.73SkamilATF_TC_HEAD(test, tc) \ 45711.73Skamil{ \ 45721.73Skamil atf_tc_set_md_var(tc, "descr", \ 45731.74Skamil "Verify " #N " (PT_SETSTEP set to: " #setstep ")"); \ 45741.73Skamil} \ 45751.73Skamil \ 45761.73SkamilATF_TC_BODY(test, tc) \ 45771.73Skamil{ \ 45781.73Skamil \ 45791.95Skamil ptrace_step(N, setstep, false, false); \ 45801.1Skamil} 45811.1Skamil 45821.73SkamilPTRACE_STEP(step1, 1, 0) 45831.73SkamilPTRACE_STEP(step2, 2, 0) 45841.73SkamilPTRACE_STEP(step3, 3, 0) 45851.73SkamilPTRACE_STEP(step4, 4, 0) 45861.73SkamilPTRACE_STEP(setstep1, 1, 1) 45871.73SkamilPTRACE_STEP(setstep2, 2, 1) 45881.73SkamilPTRACE_STEP(setstep3, 3, 1) 45891.73SkamilPTRACE_STEP(setstep4, 4, 1) 45901.95Skamil 45911.95SkamilATF_TC(step_signalmasked); 45921.95SkamilATF_TC_HEAD(step_signalmasked, tc) 45931.95Skamil{ 45941.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP"); 45951.95Skamil} 45961.95Skamil 45971.95SkamilATF_TC_BODY(step_signalmasked, tc) 45981.95Skamil{ 45991.95Skamil 46001.95Skamil ptrace_step(1, 0, true, false); 46011.95Skamil} 46021.95Skamil 46031.95SkamilATF_TC(step_signalignored); 46041.95SkamilATF_TC_HEAD(step_signalignored, tc) 46051.95Skamil{ 46061.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP"); 46071.95Skamil} 46081.95Skamil 46091.95SkamilATF_TC_BODY(step_signalignored, tc) 46101.95Skamil{ 46111.95Skamil 46121.95Skamil ptrace_step(1, 0, false, true); 46131.95Skamil} 46141.1Skamil#endif 46151.1Skamil 46161.73Skamil/// ---------------------------------------------------------------------------- 46171.1Skamil 46181.75Skamilstatic void 46191.75Skamilptrace_kill(const char *type) 46201.1Skamil{ 46211.75Skamil const int sigval = SIGSTOP; 46221.1Skamil pid_t child, wpid; 46231.1Skamil#if defined(TWAIT_HAVE_STATUS) 46241.1Skamil int status; 46251.1Skamil#endif 46261.1Skamil 46271.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 46281.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 46291.1Skamil if (child == 0) { 46301.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 46311.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 46321.1Skamil 46331.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 46341.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 46351.1Skamil 46361.1Skamil /* NOTREACHED */ 46371.1Skamil FORKEE_ASSERTX(0 && 46381.1Skamil "Child should be terminated by a signal from its parent"); 46391.1Skamil } 46401.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 46411.1Skamil 46421.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46431.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 46441.1Skamil 46451.1Skamil validate_status_stopped(status, sigval); 46461.1Skamil 46471.75Skamil DPRINTF("Before killing the child process with %s\n", type); 46481.75Skamil if (strcmp(type, "ptrace(PT_KILL)") == 0) { 46491.75Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1); 46501.75Skamil } else if (strcmp(type, "kill(SIGKILL)") == 0) { 46511.75Skamil kill(child, SIGKILL); 46521.75Skamil } else if (strcmp(type, "killpg(SIGKILL)") == 0) { 46531.75Skamil setpgid(child, 0); 46541.75Skamil killpg(getpgid(child), SIGKILL); 46551.75Skamil } 46561.1Skamil 46571.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46581.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 46591.1Skamil 46601.75Skamil validate_status_signaled(status, SIGKILL, 0); 46611.1Skamil 46621.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46631.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 46641.1Skamil} 46651.1Skamil 46661.75Skamil#define PTRACE_KILL(test, type) \ 46671.75SkamilATF_TC(test); \ 46681.75SkamilATF_TC_HEAD(test, tc) \ 46691.75Skamil{ \ 46701.75Skamil atf_tc_set_md_var(tc, "descr", \ 46711.75Skamil "Verify killing the child with " type); \ 46721.75Skamil} \ 46731.75Skamil \ 46741.75SkamilATF_TC_BODY(test, tc) \ 46751.75Skamil{ \ 46761.75Skamil \ 46771.75Skamil ptrace_kill(type); \ 46781.1Skamil} 46791.1Skamil 46801.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1 46811.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)") 46821.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)") 46831.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)") 46841.1Skamil 46851.75Skamil/// ---------------------------------------------------------------------------- 46861.1Skamil 46871.77Skamilstatic void 46881.77Skamiltraceme_lwpinfo(const int threads) 46891.1Skamil{ 46901.1Skamil const int sigval = SIGSTOP; 46911.77Skamil const int sigval2 = SIGINT; 46921.1Skamil pid_t child, wpid; 46931.1Skamil#if defined(TWAIT_HAVE_STATUS) 46941.1Skamil int status; 46951.1Skamil#endif 46961.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 46971.77Skamil struct ptrace_siginfo info; 46981.77Skamil 46991.77Skamil /* Maximum number of supported threads in this test */ 47001.77Skamil pthread_t t[3]; 47011.77Skamil int n, rv; 47021.77Skamil 47031.77Skamil ATF_REQUIRE((int)__arraycount(t) >= threads); 47041.1Skamil 47051.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 47061.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 47071.1Skamil if (child == 0) { 47081.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 47091.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 47101.1Skamil 47111.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 47121.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 47131.1Skamil 47141.77Skamil for (n = 0; n < threads; n++) { 47151.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 47161.77Skamil FORKEE_ASSERT(rv == 0); 47171.77Skamil } 47181.77Skamil 47191.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval2)); 47201.77Skamil FORKEE_ASSERT(raise(sigval2) == 0); 47211.77Skamil 47221.77Skamil /* NOTREACHED */ 47231.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 47241.1Skamil } 47251.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 47261.1Skamil 47271.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47281.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47291.1Skamil 47301.1Skamil validate_status_stopped(status, sigval); 47311.1Skamil 47321.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 47331.77Skamil SYSCALL_REQUIRE( 47341.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 47351.77Skamil 47361.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 47371.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 47381.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 47391.77Skamil info.psi_siginfo.si_errno); 47401.77Skamil 47411.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 47421.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 47431.77Skamil 47441.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 47451.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 47461.1Skamil 47471.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 47481.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 47491.1Skamil 47501.13Schristos DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n", 47511.77Skamil lwp.pl_lwpid); 47521.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 47531.1Skamil 47541.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 47551.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 47561.1Skamil 47571.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 47581.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 47591.1Skamil 47601.13Schristos DPRINTF("Before resuming the child process where it left off and " 47611.1Skamil "without signal to be sent\n"); 47621.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 47631.1Skamil 47641.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47651.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47661.1Skamil 47671.77Skamil validate_status_stopped(status, sigval2); 47681.77Skamil 47691.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 47701.77Skamil SYSCALL_REQUIRE( 47711.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 47721.77Skamil 47731.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 47741.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 47751.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 47761.77Skamil info.psi_siginfo.si_errno); 47771.77Skamil 47781.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2); 47791.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 47801.77Skamil 47811.77Skamil memset(&lwp, 0, sizeof(lwp)); 47821.77Skamil 47831.77Skamil for (n = 0; n <= threads; n++) { 47841.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 47851.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 47861.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 47871.77Skamil 47881.77Skamil DPRINTF("Assert that the thread exists\n"); 47891.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 47901.77Skamil 47911.77Skamil DPRINTF("Assert that lwp thread %d received expected event\n", 47921.77Skamil lwp.pl_lwpid); 47931.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ? 47941.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 47951.77Skamil } 47961.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 47971.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 47981.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 47991.77Skamil 48001.77Skamil DPRINTF("Assert that there are no more threads\n"); 48011.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 48021.77Skamil 48031.77Skamil DPRINTF("Before resuming the child process where it left off and " 48041.77Skamil "without signal to be sent\n"); 48051.77Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1); 48061.77Skamil 48071.77Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48081.77Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48091.77Skamil 48101.77Skamil validate_status_signaled(status, SIGKILL, 0); 48111.1Skamil 48121.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48131.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 48141.1Skamil} 48151.1Skamil 48161.77Skamil#define TRACEME_LWPINFO(test, threads) \ 48171.77SkamilATF_TC(test); \ 48181.77SkamilATF_TC_HEAD(test, tc) \ 48191.77Skamil{ \ 48201.77Skamil atf_tc_set_md_var(tc, "descr", \ 48211.77Skamil "Verify LWPINFO with the child with " #threads \ 48221.77Skamil " spawned extra threads"); \ 48231.77Skamil} \ 48241.77Skamil \ 48251.77SkamilATF_TC_BODY(test, tc) \ 48261.77Skamil{ \ 48271.77Skamil \ 48281.77Skamil traceme_lwpinfo(threads); \ 48291.1Skamil} 48301.1Skamil 48311.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0) 48321.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1) 48331.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2) 48341.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3) 48351.77Skamil 48361.77Skamil/// ---------------------------------------------------------------------------- 48371.77Skamil 48381.77Skamil#if defined(TWAIT_HAVE_PID) 48391.77Skamilstatic void 48401.77Skamilattach_lwpinfo(const int threads) 48411.1Skamil{ 48421.77Skamil const int sigval = SIGINT; 48431.1Skamil struct msg_fds parent_tracee, parent_tracer; 48441.1Skamil const int exitval_tracer = 10; 48451.1Skamil pid_t tracee, tracer, wpid; 48461.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 48471.1Skamil#if defined(TWAIT_HAVE_STATUS) 48481.1Skamil int status; 48491.1Skamil#endif 48501.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 48511.77Skamil struct ptrace_siginfo info; 48521.77Skamil 48531.77Skamil /* Maximum number of supported threads in this test */ 48541.77Skamil pthread_t t[3]; 48551.77Skamil int n, rv; 48561.1Skamil 48571.13Schristos DPRINTF("Spawn tracee\n"); 48581.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 48591.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 48601.1Skamil tracee = atf_utils_fork(); 48611.1Skamil if (tracee == 0) { 48621.1Skamil /* Wait for message from the parent */ 48631.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 48641.1Skamil 48651.77Skamil CHILD_FROM_PARENT("spawn threads", parent_tracee, msg); 48661.77Skamil 48671.77Skamil for (n = 0; n < threads; n++) { 48681.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 48691.77Skamil FORKEE_ASSERT(rv == 0); 48701.77Skamil } 48711.77Skamil 48721.77Skamil CHILD_TO_PARENT("tracee exit", parent_tracee, msg); 48731.77Skamil 48741.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 48751.77Skamil FORKEE_ASSERT(raise(sigval) == 0); 48761.77Skamil 48771.77Skamil /* NOTREACHED */ 48781.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 48791.1Skamil } 48801.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 48811.1Skamil 48821.13Schristos DPRINTF("Spawn debugger\n"); 48831.1Skamil tracer = atf_utils_fork(); 48841.1Skamil if (tracer == 0) { 48851.1Skamil /* No IPC to communicate with the child */ 48861.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 48871.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 48881.1Skamil 48891.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 48901.1Skamil FORKEE_REQUIRE_SUCCESS( 48911.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 48921.1Skamil 48931.1Skamil forkee_status_stopped(status, SIGSTOP); 48941.1Skamil 48951.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 48961.77Skamil "tracee"); 48971.77Skamil FORKEE_ASSERT( 48981.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 48991.77Skamil 49001.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 49011.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 49021.77Skamil "si_errno=%#x\n", 49031.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 49041.77Skamil info.psi_siginfo.si_errno); 49051.77Skamil 49061.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 49071.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 49081.77Skamil 49091.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 49101.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 49111.1Skamil != -1); 49121.1Skamil 49131.13Schristos DPRINTF("Assert that there exists a thread\n"); 49141.77Skamil FORKEE_ASSERTX(lwp.pl_lwpid > 0); 49151.1Skamil 49161.13Schristos DPRINTF("Assert that lwp thread %d received event " 49171.77Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 49181.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 49191.1Skamil 49201.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 49211.77Skamil "tracee\n"); 49221.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 49231.1Skamil != -1); 49241.1Skamil 49251.77Skamil DPRINTF("Assert that there are no more lwp threads in " 49261.77Skamil "tracee\n"); 49271.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 49281.1Skamil 49291.1Skamil /* Resume tracee with PT_CONTINUE */ 49301.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 49311.1Skamil 49321.1Skamil /* Inform parent that tracer has attached to tracee */ 49331.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 49341.77Skamil 49351.1Skamil /* Wait for parent */ 49361.1Skamil CHILD_FROM_PARENT("tracer wait", parent_tracer, msg); 49371.1Skamil 49381.77Skamil /* Wait for tracee and assert that it raised a signal */ 49391.77Skamil FORKEE_REQUIRE_SUCCESS( 49401.77Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 49411.77Skamil 49421.77Skamil forkee_status_stopped(status, SIGINT); 49431.77Skamil 49441.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 49451.77Skamil "child"); 49461.77Skamil FORKEE_ASSERT( 49471.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 49481.77Skamil 49491.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 49501.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 49511.77Skamil "si_errno=%#x\n", 49521.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 49531.77Skamil info.psi_siginfo.si_errno); 49541.77Skamil 49551.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 49561.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 49571.77Skamil 49581.77Skamil memset(&lwp, 0, sizeof(lwp)); 49591.77Skamil 49601.77Skamil for (n = 0; n <= threads; n++) { 49611.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 49621.77Skamil "child\n"); 49631.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, 49641.77Skamil sizeof(lwp)) != -1); 49651.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 49661.77Skamil 49671.77Skamil DPRINTF("Assert that the thread exists\n"); 49681.77Skamil FORKEE_ASSERT(lwp.pl_lwpid > 0); 49691.77Skamil 49701.77Skamil DPRINTF("Assert that lwp thread %d received expected " 49711.77Skamil "event\n", lwp.pl_lwpid); 49721.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 49731.77Skamil info.psi_lwpid == lwp.pl_lwpid ? 49741.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 49751.77Skamil } 49761.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 49771.77Skamil "tracee\n"); 49781.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 49791.77Skamil != -1); 49801.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 49811.77Skamil 49821.77Skamil DPRINTF("Assert that there are no more threads\n"); 49831.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 49841.77Skamil 49851.77Skamil DPRINTF("Before resuming the child process where it left off " 49861.77Skamil "and without signal to be sent\n"); 49871.77Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL) 49881.77Skamil != -1); 49891.77Skamil 49901.1Skamil /* Wait for tracee and assert that it exited */ 49911.1Skamil FORKEE_REQUIRE_SUCCESS( 49921.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 49931.1Skamil 49941.77Skamil forkee_status_signaled(status, SIGKILL, 0); 49951.1Skamil 49961.13Schristos DPRINTF("Before exiting of the tracer process\n"); 49971.1Skamil _exit(exitval_tracer); 49981.1Skamil } 49991.1Skamil 50001.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 50011.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 50021.1Skamil 50031.77Skamil DPRINTF("Resume the tracee and spawn threads\n"); 50041.77Skamil PARENT_TO_CHILD("spawn threads", parent_tracee, msg); 50051.77Skamil 50061.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 50071.77Skamil PARENT_FROM_CHILD("tracee exit", parent_tracee, msg); 50081.1Skamil 50091.77Skamil DPRINTF("Resume the tracer and let it detect multiple threads\n"); 50101.1Skamil PARENT_TO_CHILD("tracer wait", parent_tracer, msg); 50111.1Skamil 50121.13Schristos DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n", 50131.1Skamil TWAIT_FNAME); 50141.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 50151.1Skamil tracer); 50161.1Skamil 50171.1Skamil validate_status_exited(status, exitval_tracer); 50181.1Skamil 50191.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 50201.1Skamil TWAIT_FNAME); 50211.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 50221.1Skamil tracee); 50231.1Skamil 50241.77Skamil validate_status_signaled(status, SIGKILL, 0); 50251.1Skamil 50261.1Skamil msg_close(&parent_tracer); 50271.1Skamil msg_close(&parent_tracee); 50281.1Skamil} 50291.77Skamil 50301.77Skamil#define ATTACH_LWPINFO(test, threads) \ 50311.77SkamilATF_TC(test); \ 50321.77SkamilATF_TC_HEAD(test, tc) \ 50331.77Skamil{ \ 50341.77Skamil atf_tc_set_md_var(tc, "descr", \ 50351.77Skamil "Verify LWPINFO with the child with " #threads \ 50361.77Skamil " spawned extra threads (tracer is not the original " \ 50371.77Skamil "parent)"); \ 50381.77Skamil} \ 50391.77Skamil \ 50401.77SkamilATF_TC_BODY(test, tc) \ 50411.77Skamil{ \ 50421.77Skamil \ 50431.77Skamil attach_lwpinfo(threads); \ 50441.77Skamil} 50451.77Skamil 50461.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0) 50471.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1) 50481.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2) 50491.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3) 50501.1Skamil#endif 50511.1Skamil 50521.77Skamil/// ---------------------------------------------------------------------------- 50531.77Skamil 50541.1Skamilstatic void 50551.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught) 50561.1Skamil{ 50571.1Skamil const int exitval = 5; 50581.1Skamil const int sigval = SIGINT; 50591.1Skamil const int sigfaked = SIGTRAP; 50601.1Skamil const int sicodefaked = TRAP_BRKPT; 50611.1Skamil pid_t child, wpid; 50621.1Skamil struct sigaction sa; 50631.1Skamil#if defined(TWAIT_HAVE_STATUS) 50641.1Skamil int status; 50651.1Skamil#endif 50661.1Skamil struct ptrace_siginfo info; 50671.1Skamil memset(&info, 0, sizeof(info)); 50681.1Skamil 50691.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 50701.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 50711.1Skamil if (child == 0) { 50721.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 50731.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 50741.1Skamil 50751.79Skamil sa.sa_sigaction = sah; 50761.1Skamil sa.sa_flags = SA_SIGINFO; 50771.1Skamil sigemptyset(&sa.sa_mask); 50781.1Skamil 50791.79Skamil FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL) 50801.79Skamil != -1); 50811.1Skamil 50821.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 50831.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 50841.1Skamil 50851.79Skamil FORKEE_ASSERT_EQ(*signal_caught, 1); 50861.1Skamil 50871.13Schristos DPRINTF("Before exiting of the child process\n"); 50881.1Skamil _exit(exitval); 50891.1Skamil } 50901.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 50911.1Skamil 50921.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 50931.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 50941.1Skamil 50951.1Skamil validate_status_stopped(status, sigval); 50961.1Skamil 50971.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 50981.61Skre SYSCALL_REQUIRE( 50991.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 51001.1Skamil 51011.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 51021.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 51031.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 51041.1Skamil info.psi_siginfo.si_errno); 51051.1Skamil 51061.79Skamil if (faked) { 51071.79Skamil DPRINTF("Before setting new faked signal to signo=%d " 51081.79Skamil "si_code=%d\n", sigfaked, sicodefaked); 51091.79Skamil info.psi_siginfo.si_signo = sigfaked; 51101.79Skamil info.psi_siginfo.si_code = sicodefaked; 51111.79Skamil } 51121.1Skamil 51131.13Schristos DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n"); 51141.61Skre SYSCALL_REQUIRE( 51151.61Skre ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1); 51161.1Skamil 51171.79Skamil if (faked) { 51181.79Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 51191.79Skamil "child\n"); 51201.79Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 51211.79Skamil sizeof(info)) != -1); 51221.1Skamil 51231.79Skamil DPRINTF("Before checking siginfo_t\n"); 51241.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked); 51251.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked); 51261.79Skamil } 51271.1Skamil 51281.13Schristos DPRINTF("Before resuming the child process where it left off and " 51291.1Skamil "without signal to be sent\n"); 51301.79Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 51311.79Skamil faked ? sigfaked : sigval) != -1); 51321.1Skamil 51331.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51341.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 51351.1Skamil 51361.1Skamil validate_status_exited(status, exitval); 51371.1Skamil 51381.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51391.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 51401.1Skamil} 51411.1Skamil 51421.79Skamil#define PTRACE_SIGINFO(test, faked) \ 51431.79SkamilATF_TC(test); \ 51441.79SkamilATF_TC_HEAD(test, tc) \ 51451.79Skamil{ \ 51461.79Skamil atf_tc_set_md_var(tc, "descr", \ 51471.79Skamil "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls" \ 51481.79Skamil "with%s setting signal to new value", faked ? "" : "out"); \ 51491.79Skamil} \ 51501.79Skamil \ 51511.79Skamilstatic int test##_caught = 0; \ 51521.79Skamil \ 51531.79Skamilstatic void \ 51541.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx) \ 51551.79Skamil{ \ 51561.79Skamil if (faked) { \ 51571.79Skamil FORKEE_ASSERT_EQ(sig, SIGTRAP); \ 51581.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP); \ 51591.79Skamil FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT); \ 51601.79Skamil } else { \ 51611.79Skamil FORKEE_ASSERT_EQ(sig, SIGINT); \ 51621.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGINT); \ 51631.79Skamil FORKEE_ASSERT_EQ(info->si_code, SI_LWP); \ 51641.79Skamil } \ 51651.79Skamil \ 51661.79Skamil ++ test##_caught; \ 51671.79Skamil} \ 51681.79Skamil \ 51691.79SkamilATF_TC_BODY(test, tc) \ 51701.79Skamil{ \ 51711.79Skamil \ 51721.79Skamil ptrace_siginfo(faked, test##_sighandler, & test##_caught); \ 51731.79Skamil} 51741.79Skamil 51751.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false) 51761.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true) 51771.79Skamil 51781.79Skamil/// ---------------------------------------------------------------------------- 51791.79Skamil 51801.97Skamilstatic void 51811.97Skamiltraceme_exec(bool masked, bool ignored) 51821.1Skamil{ 51831.1Skamil const int sigval = SIGTRAP; 51841.1Skamil pid_t child, wpid; 51851.1Skamil#if defined(TWAIT_HAVE_STATUS) 51861.1Skamil int status; 51871.1Skamil#endif 51881.97Skamil struct sigaction sa; 51891.97Skamil struct ptrace_siginfo info; 51901.97Skamil sigset_t intmask; 51911.97Skamil struct kinfo_proc2 kp; 51921.97Skamil size_t len = sizeof(kp); 51931.97Skamil 51941.97Skamil int name[6]; 51951.97Skamil const size_t namelen = __arraycount(name); 51961.97Skamil ki_sigset_t kp_sigmask; 51971.97Skamil ki_sigset_t kp_sigignore; 51981.1Skamil 51991.1Skamil memset(&info, 0, sizeof(info)); 52001.1Skamil 52011.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 52021.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 52031.1Skamil if (child == 0) { 52041.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 52051.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 52061.1Skamil 52071.97Skamil if (masked) { 52081.97Skamil sigemptyset(&intmask); 52091.97Skamil sigaddset(&intmask, sigval); 52101.97Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 52111.97Skamil } 52121.97Skamil 52131.97Skamil if (ignored) { 52141.97Skamil memset(&sa, 0, sizeof(sa)); 52151.97Skamil sa.sa_handler = SIG_IGN; 52161.97Skamil sigemptyset(&sa.sa_mask); 52171.97Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 52181.97Skamil } 52191.97Skamil 52201.13Schristos DPRINTF("Before calling execve(2) from child\n"); 52211.1Skamil execlp("/bin/echo", "/bin/echo", NULL); 52221.1Skamil 52231.1Skamil FORKEE_ASSERT(0 && "Not reached"); 52241.1Skamil } 52251.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 52261.1Skamil 52271.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52281.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52291.1Skamil 52301.1Skamil validate_status_stopped(status, sigval); 52311.1Skamil 52321.97Skamil name[0] = CTL_KERN, 52331.97Skamil name[1] = KERN_PROC2, 52341.97Skamil name[2] = KERN_PROC_PID; 52351.97Skamil name[3] = getpid(); 52361.97Skamil name[4] = sizeof(kp); 52371.97Skamil name[5] = 1; 52381.97Skamil 52391.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 52401.97Skamil 52411.97Skamil if (masked) 52421.97Skamil kp_sigmask = kp.p_sigmask; 52431.97Skamil 52441.97Skamil if (ignored) 52451.97Skamil kp_sigignore = kp.p_sigignore; 52461.97Skamil 52471.97Skamil name[3] = getpid(); 52481.97Skamil 52491.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 52501.97Skamil 52511.97Skamil if (masked) { 52521.97Skamil DPRINTF("kp_sigmask=" 52531.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 52541.97Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 52551.97Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 52561.97Skamil 52571.97Skamil DPRINTF("kp.p_sigmask=" 52581.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 52591.97Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 52601.97Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 52611.97Skamil 52621.97Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 52631.97Skamil sizeof(kp_sigmask))); 52641.97Skamil } 52651.97Skamil 52661.97Skamil if (ignored) { 52671.97Skamil DPRINTF("kp_sigignore=" 52681.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 52691.97Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 52701.97Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 52711.97Skamil 52721.97Skamil DPRINTF("kp.p_sigignore=" 52731.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 52741.97Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 52751.97Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 52761.97Skamil 52771.97Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 52781.97Skamil sizeof(kp_sigignore))); 52791.97Skamil } 52801.97Skamil 52811.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 52821.61Skre SYSCALL_REQUIRE( 52831.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 52841.1Skamil 52851.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 52861.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 52871.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 52881.1Skamil info.psi_siginfo.si_errno); 52891.1Skamil 52901.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 52911.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 52921.1Skamil 52931.13Schristos DPRINTF("Before resuming the child process where it left off and " 52941.1Skamil "without signal to be sent\n"); 52951.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 52961.1Skamil 52971.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52981.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52991.1Skamil 53001.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53011.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 53021.1Skamil} 53031.1Skamil 53041.97Skamil#define TRACEME_EXEC(test, masked, ignored) \ 53051.97SkamilATF_TC(test); \ 53061.97SkamilATF_TC_HEAD(test, tc) \ 53071.97Skamil{ \ 53081.97Skamil atf_tc_set_md_var(tc, "descr", \ 53091.97Skamil "Detect SIGTRAP TRAP_EXEC from " \ 53101.97Skamil "child%s%s", masked ? " with masked signal" : "", \ 53111.97Skamil masked ? " with ignored signal" : ""); \ 53121.97Skamil} \ 53131.97Skamil \ 53141.97SkamilATF_TC_BODY(test, tc) \ 53151.97Skamil{ \ 53161.97Skamil \ 53171.97Skamil traceme_exec(masked, ignored); \ 53181.97Skamil} 53191.97Skamil 53201.97SkamilTRACEME_EXEC(traceme_exec, false, false) 53211.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false) 53221.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true) 53231.97Skamil 53241.82Skamil/// ---------------------------------------------------------------------------- 53251.82Skamil 53261.83Skamilstatic volatile int done; 53271.1Skamil 53281.83Skamilstatic void * 53291.83Skamiltrace_threads_cb(void *arg __unused) 53301.1Skamil{ 53311.1Skamil 53321.83Skamil done++; 53331.83Skamil 53341.83Skamil while (done < 3) 53351.83Skamil continue; 53361.83Skamil 53371.83Skamil return NULL; 53381.1Skamil} 53391.1Skamil 53401.83Skamilstatic void 53411.83Skamiltrace_threads(bool trace_create, bool trace_exit) 53421.1Skamil{ 53431.1Skamil const int sigval = SIGSTOP; 53441.1Skamil pid_t child, wpid; 53451.1Skamil#if defined(TWAIT_HAVE_STATUS) 53461.1Skamil int status; 53471.1Skamil#endif 53481.1Skamil ptrace_state_t state; 53491.1Skamil const int slen = sizeof(state); 53501.1Skamil ptrace_event_t event; 53511.1Skamil const int elen = sizeof(event); 53521.83Skamil struct ptrace_siginfo info; 53531.83Skamil 53541.83Skamil pthread_t t[3]; 53551.83Skamil int rv; 53561.83Skamil size_t n; 53571.1Skamil lwpid_t lid; 53581.83Skamil 53591.83Skamil /* Track created and exited threads */ 53601.83Skamil bool traced_lwps[__arraycount(t)]; 53611.83Skamil 53621.119Skamil if (trace_exit) 53631.119Skamil atf_tc_skip("PR kern/51995"); 53641.1Skamil 53651.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 53661.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 53671.1Skamil if (child == 0) { 53681.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 53691.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 53701.1Skamil 53711.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 53721.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 53731.1Skamil 53741.83Skamil for (n = 0; n < __arraycount(t); n++) { 53751.83Skamil rv = pthread_create(&t[n], NULL, trace_threads_cb, 53761.83Skamil NULL); 53771.83Skamil FORKEE_ASSERT(rv == 0); 53781.83Skamil } 53791.1Skamil 53801.83Skamil for (n = 0; n < __arraycount(t); n++) { 53811.83Skamil rv = pthread_join(t[n], NULL); 53821.83Skamil FORKEE_ASSERT(rv == 0); 53831.83Skamil } 53841.1Skamil 53851.83Skamil /* 53861.83Skamil * There is race between _exit() and pthread_join() detaching 53871.83Skamil * a thread. For simplicity kill the process after detecting 53881.83Skamil * LWP events. 53891.83Skamil */ 53901.83Skamil while (true) 53911.83Skamil continue; 53921.1Skamil 53931.83Skamil FORKEE_ASSERT(0 && "Not reached"); 53941.1Skamil } 53951.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 53961.1Skamil 53971.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53981.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 53991.1Skamil 54001.1Skamil validate_status_stopped(status, sigval); 54011.1Skamil 54021.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 54031.83Skamil SYSCALL_REQUIRE( 54041.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 54051.1Skamil 54061.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 54071.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 54081.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 54091.83Skamil info.psi_siginfo.si_errno); 54101.1Skamil 54111.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 54121.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 54131.1Skamil 54141.83Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 54151.83Skamil memset(&event, 0, sizeof(event)); 54161.83Skamil if (trace_create) 54171.83Skamil event.pe_set_event |= PTRACE_LWP_CREATE; 54181.83Skamil if (trace_exit) 54191.83Skamil event.pe_set_event |= PTRACE_LWP_EXIT; 54201.83Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 54211.1Skamil 54221.13Schristos DPRINTF("Before resuming the child process where it left off and " 54231.1Skamil "without signal to be sent\n"); 54241.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 54251.1Skamil 54261.83Skamil memset(traced_lwps, 0, sizeof(traced_lwps)); 54271.1Skamil 54281.83Skamil for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) { 54291.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 54301.83Skamil "SIGTRAP\n", TWAIT_FNAME); 54311.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 54321.83Skamil child); 54331.1Skamil 54341.83Skamil validate_status_stopped(status, SIGTRAP); 54351.1Skamil 54361.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 54371.83Skamil "child\n"); 54381.83Skamil SYSCALL_REQUIRE( 54391.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 54401.1Skamil 54411.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 54421.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 54431.83Skamil "si_errno=%#x\n", 54441.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 54451.83Skamil info.psi_siginfo.si_errno); 54461.1Skamil 54471.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 54481.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 54491.1Skamil 54501.83Skamil SYSCALL_REQUIRE( 54511.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 54521.1Skamil 54531.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 54541.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 54551.1Skamil 54561.83Skamil lid = state.pe_lwp; 54571.83Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 54581.1Skamil 54591.83Skamil traced_lwps[lid - 1] = true; 54601.1Skamil 54611.83Skamil DPRINTF("Before resuming the child process where it left off " 54621.83Skamil "and without signal to be sent\n"); 54631.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 54641.83Skamil } 54651.1Skamil 54661.83Skamil for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) { 54671.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 54681.83Skamil "SIGTRAP\n", TWAIT_FNAME); 54691.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 54701.83Skamil child); 54711.1Skamil 54721.83Skamil validate_status_stopped(status, SIGTRAP); 54731.1Skamil 54741.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 54751.83Skamil "child\n"); 54761.83Skamil SYSCALL_REQUIRE( 54771.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 54781.1Skamil 54791.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 54801.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 54811.83Skamil "si_errno=%#x\n", 54821.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 54831.83Skamil info.psi_siginfo.si_errno); 54841.1Skamil 54851.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 54861.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 54871.1Skamil 54881.83Skamil SYSCALL_REQUIRE( 54891.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 54901.1Skamil 54911.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 54921.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 54931.1Skamil 54941.83Skamil lid = state.pe_lwp; 54951.83Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 54961.1Skamil 54971.83Skamil if (trace_create) { 54981.83Skamil ATF_REQUIRE(traced_lwps[lid - 1] == true); 54991.83Skamil traced_lwps[lid - 1] = false; 55001.83Skamil } 55011.1Skamil 55021.83Skamil DPRINTF("Before resuming the child process where it left off " 55031.83Skamil "and without signal to be sent\n"); 55041.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 55051.83Skamil } 55061.1Skamil 55071.83Skamil kill(child, SIGKILL); 55081.1Skamil 55091.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 55101.1Skamil TWAIT_FNAME); 55111.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 55121.1Skamil 55131.83Skamil validate_status_signaled(status, SIGKILL, 0); 55141.1Skamil 55151.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 55161.1Skamil TWAIT_FNAME); 55171.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 55181.1Skamil} 55191.1Skamil 55201.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit) \ 55211.83SkamilATF_TC(test); \ 55221.83SkamilATF_TC_HEAD(test, tc) \ 55231.83Skamil{ \ 55241.83Skamil atf_tc_set_md_var(tc, "descr", \ 55251.83Skamil "Verify spawning threads with%s tracing LWP create and" \ 55261.83Skamil "with%s tracing LWP exit", trace_create ? "" : "out", \ 55271.83Skamil trace_exit ? "" : "out"); \ 55281.83Skamil} \ 55291.83Skamil \ 55301.83SkamilATF_TC_BODY(test, tc) \ 55311.83Skamil{ \ 55321.83Skamil \ 55331.83Skamil trace_threads(trace_create, trace_exit); \ 55341.83Skamil} 55351.83Skamil 55361.119SkamilTRACE_THREADS(trace_thread_nolwpevents, false, false) 55371.119SkamilTRACE_THREADS(trace_thread_lwpexit, false, true) 55381.119SkamilTRACE_THREADS(trace_thread_lwpcreate, true, false) 55391.119SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true) 55401.83Skamil 55411.83Skamil/// ---------------------------------------------------------------------------- 55421.83Skamil 55431.84SkamilATF_TC(signal_mask_unrelated); 55441.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc) 55451.1Skamil{ 55461.1Skamil atf_tc_set_md_var(tc, "descr", 55471.1Skamil "Verify that masking single unrelated signal does not stop tracer " 55481.1Skamil "from catching other signals"); 55491.1Skamil} 55501.1Skamil 55511.84SkamilATF_TC_BODY(signal_mask_unrelated, tc) 55521.1Skamil{ 55531.1Skamil const int exitval = 5; 55541.1Skamil const int sigval = SIGSTOP; 55551.1Skamil const int sigmasked = SIGTRAP; 55561.1Skamil const int signotmasked = SIGINT; 55571.1Skamil pid_t child, wpid; 55581.1Skamil#if defined(TWAIT_HAVE_STATUS) 55591.1Skamil int status; 55601.1Skamil#endif 55611.1Skamil sigset_t intmask; 55621.1Skamil 55631.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 55641.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 55651.1Skamil if (child == 0) { 55661.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 55671.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 55681.1Skamil 55691.1Skamil sigemptyset(&intmask); 55701.1Skamil sigaddset(&intmask, sigmasked); 55711.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 55721.1Skamil 55731.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 55741.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 55751.1Skamil 55761.13Schristos DPRINTF("Before raising %s from child\n", 55771.1Skamil strsignal(signotmasked)); 55781.1Skamil FORKEE_ASSERT(raise(signotmasked) == 0); 55791.1Skamil 55801.13Schristos DPRINTF("Before exiting of the child process\n"); 55811.1Skamil _exit(exitval); 55821.1Skamil } 55831.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 55841.1Skamil 55851.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 55861.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 55871.1Skamil 55881.1Skamil validate_status_stopped(status, sigval); 55891.1Skamil 55901.13Schristos DPRINTF("Before resuming the child process where it left off and " 55911.1Skamil "without signal to be sent\n"); 55921.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 55931.1Skamil 55941.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 55951.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 55961.1Skamil 55971.1Skamil validate_status_stopped(status, signotmasked); 55981.1Skamil 55991.13Schristos DPRINTF("Before resuming the child process where it left off and " 56001.1Skamil "without signal to be sent\n"); 56011.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56021.1Skamil 56031.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56041.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56051.1Skamil 56061.1Skamil validate_status_exited(status, exitval); 56071.1Skamil 56081.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56091.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 56101.1Skamil} 56111.1Skamil 56121.84Skamil/// ---------------------------------------------------------------------------- 56131.84Skamil 56141.1Skamil#if defined(TWAIT_HAVE_PID) 56151.99Skamilstatic void 56161.99Skamilfork2_body(bool trackfork, bool trackvfork, bool trackvforkdone, bool masked, 56171.99Skamil bool ignored) 56181.1Skamil{ 56191.1Skamil const int exitval = 5; 56201.1Skamil const int exitval2 = 15; 56211.1Skamil const int sigval = SIGSTOP; 56221.99Skamil pid_t child, child2 = 0, wpid; 56231.1Skamil#if defined(TWAIT_HAVE_STATUS) 56241.1Skamil int status; 56251.1Skamil#endif 56261.1Skamil ptrace_state_t state; 56271.1Skamil const int slen = sizeof(state); 56281.1Skamil ptrace_event_t event; 56291.1Skamil const int elen = sizeof(event); 56301.99Skamil pid_t (*fn)(void); 56311.99Skamil struct sigaction sa; 56321.99Skamil struct ptrace_siginfo info; 56331.99Skamil sigset_t intmask; 56341.99Skamil struct kinfo_proc2 kp; 56351.99Skamil size_t len = sizeof(kp); 56361.99Skamil 56371.99Skamil int name[6]; 56381.99Skamil const size_t namelen = __arraycount(name); 56391.99Skamil ki_sigset_t kp_sigmask; 56401.99Skamil ki_sigset_t kp_sigignore; 56411.1Skamil 56421.99Skamil if (trackfork) 56431.99Skamil fn = fork; 56441.99Skamil if (trackvfork || trackvforkdone) 56451.99Skamil fn = vfork; 56461.14Schristos 56471.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 56481.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 56491.1Skamil if (child == 0) { 56501.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 56511.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 56521.1Skamil 56531.99Skamil if (masked) { 56541.99Skamil sigemptyset(&intmask); 56551.99Skamil sigaddset(&intmask, SIGTRAP); 56561.99Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 56571.99Skamil } 56581.99Skamil 56591.99Skamil if (ignored) { 56601.99Skamil memset(&sa, 0, sizeof(sa)); 56611.99Skamil sa.sa_handler = SIG_IGN; 56621.99Skamil sigemptyset(&sa.sa_mask); 56631.99Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 56641.99Skamil } 56651.1Skamil 56661.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 56671.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 56681.1Skamil 56691.99Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 56701.1Skamil 56711.1Skamil if (child2 == 0) 56721.1Skamil _exit(exitval2); 56731.1Skamil 56741.1Skamil FORKEE_REQUIRE_SUCCESS 56751.99Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 56761.1Skamil 56771.1Skamil forkee_status_exited(status, exitval2); 56781.1Skamil 56791.13Schristos DPRINTF("Before exiting of the child process\n"); 56801.1Skamil _exit(exitval); 56811.1Skamil } 56821.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 56831.1Skamil 56841.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56851.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56861.1Skamil 56871.1Skamil validate_status_stopped(status, sigval); 56881.1Skamil 56891.99Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 56901.99Skamil SYSCALL_REQUIRE( 56911.99Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 56921.99Skamil 56931.99Skamil DPRINTF("Before checking siginfo_t\n"); 56941.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 56951.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 56961.1Skamil 56971.99Skamil name[0] = CTL_KERN, 56981.99Skamil name[1] = KERN_PROC2, 56991.99Skamil name[2] = KERN_PROC_PID; 57001.99Skamil name[3] = child; 57011.99Skamil name[4] = sizeof(kp); 57021.99Skamil name[5] = 1; 57031.1Skamil 57041.99Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 57051.1Skamil 57061.99Skamil if (masked) 57071.99Skamil kp_sigmask = kp.p_sigmask; 57081.1Skamil 57091.99Skamil if (ignored) 57101.99Skamil kp_sigignore = kp.p_sigignore; 57111.1Skamil 57121.99Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 57131.99Skamil trackfork ? "|PTRACE_FORK" : "", 57141.99Skamil trackvfork ? "|PTRACE_VFORK" : "", 57151.99Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 57161.99Skamil event.pe_set_event = 0; 57171.99Skamil if (trackfork) 57181.99Skamil event.pe_set_event |= PTRACE_FORK; 57191.99Skamil if (trackvfork) 57201.99Skamil event.pe_set_event |= PTRACE_VFORK; 57211.99Skamil if (trackvforkdone) 57221.99Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 57231.99Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 57241.1Skamil 57251.99Skamil DPRINTF("Before resuming the child process where it left off and " 57261.99Skamil "without signal to be sent\n"); 57271.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 57281.1Skamil 57291.99Skamil if (trackfork || trackvfork) { 57301.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 57311.99Skamil child); 57321.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 57331.99Skamil child); 57341.1Skamil 57351.99Skamil validate_status_stopped(status, SIGTRAP); 57361.1Skamil 57371.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 57381.1Skamil 57391.99Skamil if (masked) { 57401.99Skamil DPRINTF("kp_sigmask=" 57411.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 57421.99Skamil PRIx32 "\n", 57431.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 57441.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 57451.1Skamil 57461.99Skamil DPRINTF("kp.p_sigmask=" 57471.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 57481.99Skamil PRIx32 "\n", 57491.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 57501.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 57511.1Skamil 57521.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 57531.99Skamil sizeof(kp_sigmask))); 57541.99Skamil } 57551.1Skamil 57561.99Skamil if (ignored) { 57571.99Skamil DPRINTF("kp_sigignore=" 57581.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 57591.99Skamil PRIx32 "\n", 57601.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 57611.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 57621.1Skamil 57631.99Skamil DPRINTF("kp.p_sigignore=" 57641.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 57651.99Skamil PRIx32 "\n", 57661.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 57671.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 57681.1Skamil 57691.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 57701.99Skamil sizeof(kp_sigignore))); 57711.99Skamil } 57721.1Skamil 57731.99Skamil SYSCALL_REQUIRE( 57741.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 57751.99Skamil if (trackfork) { 57761.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 57771.99Skamil PTRACE_FORK); 57781.99Skamil } 57791.99Skamil if (trackvfork) { 57801.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 57811.99Skamil PTRACE_VFORK); 57821.99Skamil } 57831.1Skamil 57841.99Skamil child2 = state.pe_other_pid; 57851.99Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 57861.1Skamil 57871.99Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 57881.99Skamil "%d\n", TWAIT_FNAME, child2, child); 57891.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 57901.99Skamil child2); 57911.1Skamil 57921.99Skamil validate_status_stopped(status, SIGTRAP); 57931.1Skamil 57941.99Skamil name[3] = child2; 57951.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 57961.1Skamil 57971.99Skamil if (masked) { 57981.99Skamil DPRINTF("kp_sigmask=" 57991.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58001.99Skamil PRIx32 "\n", 58011.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 58021.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 58031.1Skamil 58041.99Skamil DPRINTF("kp.p_sigmask=" 58051.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58061.99Skamil PRIx32 "\n", 58071.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 58081.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 58091.14Schristos 58101.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 58111.99Skamil sizeof(kp_sigmask))); 58121.99Skamil } 58131.1Skamil 58141.99Skamil if (ignored) { 58151.99Skamil DPRINTF("kp_sigignore=" 58161.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58171.99Skamil PRIx32 "\n", 58181.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 58191.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 58201.1Skamil 58211.99Skamil DPRINTF("kp.p_sigignore=" 58221.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58231.99Skamil PRIx32 "\n", 58241.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 58251.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 58261.1Skamil 58271.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 58281.99Skamil sizeof(kp_sigignore))); 58291.99Skamil } 58301.1Skamil 58311.99Skamil SYSCALL_REQUIRE( 58321.99Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 58331.99Skamil if (trackfork) { 58341.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 58351.99Skamil PTRACE_FORK); 58361.99Skamil } 58371.99Skamil if (trackvfork) { 58381.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 58391.99Skamil PTRACE_VFORK); 58401.99Skamil } 58411.1Skamil 58421.99Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 58431.1Skamil 58441.99Skamil DPRINTF("Before resuming the forkee process where it left off " 58451.99Skamil "and without signal to be sent\n"); 58461.99Skamil SYSCALL_REQUIRE( 58471.99Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 58481.1Skamil 58491.99Skamil DPRINTF("Before resuming the child process where it left off " 58501.99Skamil "and without signal to be sent\n"); 58511.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 58521.1Skamil } 58531.1Skamil 58541.99Skamil if (trackvforkdone) { 58551.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 58561.99Skamil child); 58571.99Skamil TWAIT_REQUIRE_SUCCESS( 58581.99Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 58591.1Skamil 58601.99Skamil validate_status_stopped(status, SIGTRAP); 58611.1Skamil 58621.99Skamil name[3] = child; 58631.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 58641.1Skamil 58651.102Skamil /* 58661.102Skamil * SIGCHLD is now pending in the signal queue and 58671.102Skamil * the kernel presents it to userland as a masked signal. 58681.102Skamil */ 58691.102Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 58701.102Skamil 58711.99Skamil if (masked) { 58721.99Skamil DPRINTF("kp_sigmask=" 58731.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58741.99Skamil PRIx32 "\n", 58751.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 58761.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 58771.1Skamil 58781.99Skamil DPRINTF("kp.p_sigmask=" 58791.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58801.99Skamil PRIx32 "\n", 58811.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 58821.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 58831.1Skamil 58841.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 58851.99Skamil sizeof(kp_sigmask))); 58861.99Skamil } 58871.1Skamil 58881.99Skamil if (ignored) { 58891.99Skamil DPRINTF("kp_sigignore=" 58901.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58911.99Skamil PRIx32 "\n", 58921.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 58931.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 58941.1Skamil 58951.99Skamil DPRINTF("kp.p_sigignore=" 58961.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58971.99Skamil PRIx32 "\n", 58981.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 58991.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 59001.1Skamil 59011.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 59021.99Skamil sizeof(kp_sigignore))); 59031.99Skamil } 59041.1Skamil 59051.99Skamil SYSCALL_REQUIRE( 59061.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 59071.99Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 59081.1Skamil 59091.99Skamil child2 = state.pe_other_pid; 59101.99Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 59111.99Skamil child2); 59121.1Skamil 59131.99Skamil DPRINTF("Before resuming the child process where it left off " 59141.99Skamil "and without signal to be sent\n"); 59151.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 59161.99Skamil } 59171.1Skamil 59181.99Skamil if (trackfork || trackvfork) { 59191.99Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 59201.99Skamil "\n", TWAIT_FNAME); 59211.99Skamil TWAIT_REQUIRE_SUCCESS( 59221.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 59231.1Skamil 59241.99Skamil validate_status_exited(status, exitval2); 59251.1Skamil 59261.99Skamil DPRINTF("Before calling %s() for the forkee - expected no " 59271.99Skamil "process\n", TWAIT_FNAME); 59281.99Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 59291.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 59301.99Skamil } 59311.1Skamil 59321.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 59331.1Skamil "SIGCHLD\n", TWAIT_FNAME); 59341.57Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 59351.1Skamil 59361.1Skamil validate_status_stopped(status, SIGCHLD); 59371.1Skamil 59381.57Skamil DPRINTF("Before resuming the child process where it left off and " 59391.1Skamil "without signal to be sent\n"); 59401.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 59411.1Skamil 59421.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 59431.1Skamil TWAIT_FNAME); 59441.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 59451.1Skamil 59461.1Skamil validate_status_exited(status, exitval); 59471.1Skamil 59481.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 59491.57Skamil TWAIT_FNAME); 59501.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 59511.1Skamil} 59521.1Skamil 59531.99Skamil#define FORK2_TEST(name,trackfork,trackvfork,trackvforkdone, \ 59541.99Skamil masked,ignored) \ 59551.99SkamilATF_TC(name); \ 59561.99SkamilATF_TC_HEAD(name, tc) \ 59571.99Skamil{ \ 59581.99Skamil atf_tc_set_md_var(tc, "descr", "Verify that %s%s%s is caught " \ 59591.99Skamil "regardless of signal %s%s", \ 59601.99Skamil trackfork ? "PTRACE_FORK" : "", \ 59611.99Skamil trackvfork ? "PTRACE_VFORK" : "", \ 59621.99Skamil trackvforkdone ? "PTRACE_VFORK_DONE" : "", \ 59631.99Skamil masked ? "masked" : "", ignored ? "ignored" : ""); \ 59641.99Skamil} \ 59651.99Skamil \ 59661.99SkamilATF_TC_BODY(name, tc) \ 59671.99Skamil{ \ 59681.99Skamil \ 59691.99Skamil fork2_body(trackfork, trackvfork, trackvforkdone, masked, \ 59701.99Skamil ignored); \ 59711.1Skamil} 59721.1Skamil 59731.99SkamilFORK2_TEST(fork_singalmasked, true, false, false, true, false) 59741.99SkamilFORK2_TEST(fork_singalignored, true, false, false, false, true) 59751.110Skamil#if TEST_VFORK_ENABLED 59761.99SkamilFORK2_TEST(vfork_singalmasked, false, true, false, true, false) 59771.99SkamilFORK2_TEST(vfork_singalignored, false, true, false, false, true) 59781.99SkamilFORK2_TEST(vforkdone_singalmasked, false, false, true, true, false) 59791.99SkamilFORK2_TEST(vforkdone_singalignored, false, false, true, false, true) 59801.1Skamil#endif 59811.110Skamil#endif 59821.1Skamil 59831.99Skamil/// ---------------------------------------------------------------------------- 59841.1Skamil 59851.83Skamilvolatile lwpid_t the_lwp_id = 0; 59861.83Skamil 59871.83Skamilstatic void 59881.83Skamillwp_main_func(void *arg) 59891.83Skamil{ 59901.83Skamil the_lwp_id = _lwp_self(); 59911.83Skamil _lwp_exit(); 59921.83Skamil} 59931.83Skamil 59941.1SkamilATF_TC(signal9); 59951.1SkamilATF_TC_HEAD(signal9, tc) 59961.1Skamil{ 59971.1Skamil atf_tc_set_md_var(tc, "descr", 59981.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 59991.1Skamil "catching PTRACE_LWP_CREATE breakpoint"); 60001.1Skamil} 60011.1Skamil 60021.1SkamilATF_TC_BODY(signal9, tc) 60031.1Skamil{ 60041.1Skamil const int exitval = 5; 60051.1Skamil const int sigval = SIGSTOP; 60061.1Skamil const int sigmasked = SIGTRAP; 60071.1Skamil pid_t child, wpid; 60081.1Skamil#if defined(TWAIT_HAVE_STATUS) 60091.1Skamil int status; 60101.1Skamil#endif 60111.1Skamil sigset_t intmask; 60121.1Skamil ptrace_state_t state; 60131.1Skamil const int slen = sizeof(state); 60141.1Skamil ptrace_event_t event; 60151.1Skamil const int elen = sizeof(event); 60161.1Skamil ucontext_t uc; 60171.1Skamil lwpid_t lid; 60181.1Skamil static const size_t ssize = 16*1024; 60191.1Skamil void *stack; 60201.1Skamil 60211.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 60221.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 60231.1Skamil if (child == 0) { 60241.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 60251.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 60261.1Skamil 60271.1Skamil sigemptyset(&intmask); 60281.1Skamil sigaddset(&intmask, sigmasked); 60291.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 60301.1Skamil 60311.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 60321.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 60331.1Skamil 60341.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 60351.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 60361.1Skamil 60371.13Schristos DPRINTF("Before making context for new lwp in child\n"); 60381.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 60391.1Skamil 60401.13Schristos DPRINTF("Before creating new in child\n"); 60411.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 60421.1Skamil 60431.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 60441.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 60451.1Skamil 60461.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 60471.1Skamil "are the same\n", lid, the_lwp_id); 60481.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 60491.1Skamil 60501.13Schristos DPRINTF("Before exiting of the child process\n"); 60511.1Skamil _exit(exitval); 60521.1Skamil } 60531.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 60541.1Skamil 60551.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 60561.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60571.1Skamil 60581.1Skamil validate_status_stopped(status, sigval); 60591.1Skamil 60601.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 60611.1Skamil event.pe_set_event = PTRACE_LWP_CREATE; 60621.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 60631.1Skamil 60641.13Schristos DPRINTF("Before resuming the child process where it left off and " 60651.1Skamil "without signal to be sent\n"); 60661.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60671.1Skamil 60681.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 60691.1Skamil "SIGTRAP\n", TWAIT_FNAME); 60701.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60711.1Skamil 60721.1Skamil validate_status_stopped(status, sigmasked); 60731.1Skamil 60741.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 60751.1Skamil 60761.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE); 60771.1Skamil 60781.1Skamil lid = state.pe_lwp; 60791.13Schristos DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 60801.1Skamil 60811.13Schristos DPRINTF("Before resuming the child process where it left off and " 60821.1Skamil "without signal to be sent\n"); 60831.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60841.1Skamil 60851.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 60861.1Skamil TWAIT_FNAME); 60871.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60881.1Skamil 60891.1Skamil validate_status_exited(status, exitval); 60901.1Skamil 60911.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 60921.1Skamil TWAIT_FNAME); 60931.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 60941.1Skamil} 60951.1Skamil 60961.1SkamilATF_TC(signal10); 60971.1SkamilATF_TC_HEAD(signal10, tc) 60981.1Skamil{ 60991.1Skamil atf_tc_set_md_var(tc, "descr", 61001.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 61011.1Skamil "catching PTRACE_LWP_EXIT breakpoint"); 61021.1Skamil} 61031.1Skamil 61041.1SkamilATF_TC_BODY(signal10, tc) 61051.1Skamil{ 61061.1Skamil const int exitval = 5; 61071.1Skamil const int sigval = SIGSTOP; 61081.1Skamil const int sigmasked = SIGTRAP; 61091.1Skamil pid_t child, wpid; 61101.1Skamil#if defined(TWAIT_HAVE_STATUS) 61111.1Skamil int status; 61121.1Skamil#endif 61131.1Skamil sigset_t intmask; 61141.1Skamil ptrace_state_t state; 61151.1Skamil const int slen = sizeof(state); 61161.1Skamil ptrace_event_t event; 61171.1Skamil const int elen = sizeof(event); 61181.1Skamil ucontext_t uc; 61191.1Skamil lwpid_t lid; 61201.1Skamil static const size_t ssize = 16*1024; 61211.1Skamil void *stack; 61221.1Skamil 61231.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 61241.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 61251.1Skamil if (child == 0) { 61261.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 61271.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 61281.1Skamil 61291.1Skamil sigemptyset(&intmask); 61301.1Skamil sigaddset(&intmask, sigmasked); 61311.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 61321.1Skamil 61331.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 61341.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 61351.1Skamil 61361.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 61371.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 61381.1Skamil 61391.13Schristos DPRINTF("Before making context for new lwp in child\n"); 61401.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 61411.1Skamil 61421.13Schristos DPRINTF("Before creating new in child\n"); 61431.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 61441.1Skamil 61451.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 61461.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 61471.1Skamil 61481.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 61491.1Skamil "are the same\n", lid, the_lwp_id); 61501.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 61511.1Skamil 61521.13Schristos DPRINTF("Before exiting of the child process\n"); 61531.1Skamil _exit(exitval); 61541.1Skamil } 61551.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 61561.1Skamil 61571.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 61581.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61591.1Skamil 61601.1Skamil validate_status_stopped(status, sigval); 61611.1Skamil 61621.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 61631.1Skamil event.pe_set_event = PTRACE_LWP_EXIT; 61641.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 61651.1Skamil 61661.13Schristos DPRINTF("Before resuming the child process where it left off and " 61671.1Skamil "without signal to be sent\n"); 61681.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 61691.1Skamil 61701.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 61711.1Skamil "SIGTRAP\n", TWAIT_FNAME); 61721.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61731.1Skamil 61741.1Skamil validate_status_stopped(status, sigmasked); 61751.1Skamil 61761.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 61771.1Skamil 61781.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT); 61791.1Skamil 61801.1Skamil lid = state.pe_lwp; 61811.13Schristos DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 61821.1Skamil 61831.13Schristos DPRINTF("Before resuming the child process where it left off and " 61841.1Skamil "without signal to be sent\n"); 61851.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 61861.1Skamil 61871.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 61881.1Skamil TWAIT_FNAME); 61891.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61901.1Skamil 61911.1Skamil validate_status_exited(status, exitval); 61921.1Skamil 61931.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 61941.1Skamil TWAIT_FNAME); 61951.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 61961.1Skamil} 61971.1Skamil 61981.1Skamilstatic void 61991.1Skamillwp_main_stop(void *arg) 62001.1Skamil{ 62011.1Skamil the_lwp_id = _lwp_self(); 62021.1Skamil 62031.1Skamil raise(SIGTRAP); 62041.1Skamil 62051.1Skamil _lwp_exit(); 62061.1Skamil} 62071.1Skamil 62081.1SkamilATF_TC(suspend1); 62091.1SkamilATF_TC_HEAD(suspend1, tc) 62101.1Skamil{ 62111.1Skamil atf_tc_set_md_var(tc, "descr", 62121.1Skamil "Verify that a thread can be suspended by a debugger and later " 62131.1Skamil "resumed by a tracee"); 62141.1Skamil} 62151.1Skamil 62161.1SkamilATF_TC_BODY(suspend1, tc) 62171.1Skamil{ 62181.1Skamil const int exitval = 5; 62191.1Skamil const int sigval = SIGSTOP; 62201.1Skamil pid_t child, wpid; 62211.1Skamil#if defined(TWAIT_HAVE_STATUS) 62221.1Skamil int status; 62231.1Skamil#endif 62241.1Skamil ucontext_t uc; 62251.1Skamil lwpid_t lid; 62261.1Skamil static const size_t ssize = 16*1024; 62271.1Skamil void *stack; 62281.1Skamil struct ptrace_lwpinfo pl; 62291.1Skamil struct ptrace_siginfo psi; 62301.1Skamil volatile int go = 0; 62311.1Skamil 62321.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 62331.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 62341.1Skamil if (child == 0) { 62351.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 62361.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 62371.1Skamil 62381.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 62391.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 62401.1Skamil 62411.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 62421.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 62431.1Skamil 62441.13Schristos DPRINTF("Before making context for new lwp in child\n"); 62451.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 62461.1Skamil 62471.13Schristos DPRINTF("Before creating new in child\n"); 62481.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 62491.1Skamil 62501.1Skamil while (go == 0) 62511.1Skamil continue; 62521.1Skamil 62531.1Skamil raise(SIGINT); 62541.1Skamil 62551.1Skamil FORKEE_ASSERT(_lwp_continue(lid) == 0); 62561.1Skamil 62571.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 62581.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 62591.1Skamil 62601.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 62611.1Skamil "are the same\n", lid, the_lwp_id); 62621.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 62631.1Skamil 62641.13Schristos DPRINTF("Before exiting of the child process\n"); 62651.1Skamil _exit(exitval); 62661.1Skamil } 62671.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 62681.1Skamil 62691.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 62701.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62711.1Skamil 62721.1Skamil validate_status_stopped(status, sigval); 62731.1Skamil 62741.13Schristos DPRINTF("Before resuming the child process where it left off and " 62751.1Skamil "without signal to be sent\n"); 62761.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 62771.1Skamil 62781.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 62791.1Skamil "SIGTRAP\n", TWAIT_FNAME); 62801.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62811.1Skamil 62821.1Skamil validate_status_stopped(status, SIGTRAP); 62831.1Skamil 62841.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 62851.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 62861.1Skamil 62871.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 62881.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 62891.1Skamil 62901.13Schristos DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n", 62911.1Skamil child, getpid()); 62921.13Schristos SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1); 62931.1Skamil 62941.13Schristos DPRINTF("Before resuming the child process where it left off and " 62951.1Skamil "without signal to be sent\n"); 62961.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 62971.1Skamil 62981.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 62991.1Skamil "SIGINT\n", TWAIT_FNAME); 63001.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63011.1Skamil 63021.1Skamil validate_status_stopped(status, SIGINT); 63031.1Skamil 63041.1Skamil pl.pl_lwpid = 0; 63051.1Skamil 63061.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 63071.1Skamil while (pl.pl_lwpid != 0) { 63081.1Skamil 63091.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 63101.1Skamil switch (pl.pl_lwpid) { 63111.1Skamil case 1: 63121.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 63131.1Skamil break; 63141.1Skamil case 2: 63151.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 63161.1Skamil break; 63171.1Skamil } 63181.1Skamil } 63191.1Skamil 63201.13Schristos DPRINTF("Before resuming the child process where it left off and " 63211.1Skamil "without signal to be sent\n"); 63221.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63231.1Skamil 63241.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 63251.1Skamil TWAIT_FNAME); 63261.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63271.1Skamil 63281.1Skamil validate_status_exited(status, exitval); 63291.1Skamil 63301.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 63311.1Skamil TWAIT_FNAME); 63321.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 63331.1Skamil} 63341.1Skamil 63351.1SkamilATF_TC(suspend2); 63361.1SkamilATF_TC_HEAD(suspend2, tc) 63371.1Skamil{ 63381.1Skamil atf_tc_set_md_var(tc, "descr", 63391.1Skamil "Verify that the while the only thread within a process is " 63401.1Skamil "suspended, the whole process cannot be unstopped"); 63411.1Skamil} 63421.1Skamil 63431.1SkamilATF_TC_BODY(suspend2, tc) 63441.1Skamil{ 63451.1Skamil const int exitval = 5; 63461.1Skamil const int sigval = SIGSTOP; 63471.1Skamil pid_t child, wpid; 63481.1Skamil#if defined(TWAIT_HAVE_STATUS) 63491.1Skamil int status; 63501.1Skamil#endif 63511.1Skamil struct ptrace_siginfo psi; 63521.1Skamil 63531.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 63541.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 63551.1Skamil if (child == 0) { 63561.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 63571.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 63581.1Skamil 63591.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 63601.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 63611.1Skamil 63621.13Schristos DPRINTF("Before exiting of the child process\n"); 63631.1Skamil _exit(exitval); 63641.1Skamil } 63651.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 63661.1Skamil 63671.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 63681.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63691.1Skamil 63701.1Skamil validate_status_stopped(status, sigval); 63711.1Skamil 63721.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 63731.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 63741.1Skamil 63751.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 63761.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 63771.1Skamil 63781.13Schristos DPRINTF("Before resuming the child process where it left off and " 63791.1Skamil "without signal to be sent\n"); 63801.1Skamil ATF_REQUIRE_ERRNO(EDEADLK, 63811.1Skamil ptrace(PT_CONTINUE, child, (void *)1, 0) == -1); 63821.1Skamil 63831.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 63841.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 63851.1Skamil 63861.13Schristos DPRINTF("Before resuming the child process where it left off and " 63871.1Skamil "without signal to be sent\n"); 63881.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63891.1Skamil 63901.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 63911.1Skamil TWAIT_FNAME); 63921.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63931.1Skamil 63941.1Skamil validate_status_exited(status, exitval); 63951.1Skamil 63961.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 63971.1Skamil TWAIT_FNAME); 63981.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 63991.1Skamil} 64001.1Skamil 64011.1SkamilATF_TC(resume1); 64021.1SkamilATF_TC_HEAD(resume1, tc) 64031.1Skamil{ 64041.1Skamil atf_tc_set_md_var(tc, "descr", 64051.1Skamil "Verify that a thread can be suspended by a debugger and later " 64061.1Skamil "resumed by the debugger"); 64071.1Skamil} 64081.1Skamil 64091.1SkamilATF_TC_BODY(resume1, tc) 64101.1Skamil{ 64111.1Skamil struct msg_fds fds; 64121.1Skamil const int exitval = 5; 64131.1Skamil const int sigval = SIGSTOP; 64141.1Skamil pid_t child, wpid; 64151.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 64161.1Skamil#if defined(TWAIT_HAVE_STATUS) 64171.1Skamil int status; 64181.1Skamil#endif 64191.1Skamil ucontext_t uc; 64201.1Skamil lwpid_t lid; 64211.1Skamil static const size_t ssize = 16*1024; 64221.1Skamil void *stack; 64231.1Skamil struct ptrace_lwpinfo pl; 64241.1Skamil struct ptrace_siginfo psi; 64251.1Skamil 64261.13Schristos SYSCALL_REQUIRE(msg_open(&fds) == 0); 64271.1Skamil 64281.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 64291.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 64301.1Skamil if (child == 0) { 64311.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 64321.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 64331.1Skamil 64341.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 64351.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 64361.1Skamil 64371.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 64381.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 64391.1Skamil 64401.13Schristos DPRINTF("Before making context for new lwp in child\n"); 64411.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 64421.1Skamil 64431.13Schristos DPRINTF("Before creating new in child\n"); 64441.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 64451.1Skamil 64461.1Skamil CHILD_TO_PARENT("Message", fds, msg); 64471.1Skamil 64481.1Skamil raise(SIGINT); 64491.1Skamil 64501.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 64511.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 64521.1Skamil 64531.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 64541.1Skamil "are the same\n", lid, the_lwp_id); 64551.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 64561.1Skamil 64571.13Schristos DPRINTF("Before exiting of the child process\n"); 64581.1Skamil _exit(exitval); 64591.1Skamil } 64601.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 64611.1Skamil 64621.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 64631.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64641.1Skamil 64651.1Skamil validate_status_stopped(status, sigval); 64661.1Skamil 64671.13Schristos DPRINTF("Before resuming the child process where it left off and " 64681.1Skamil "without signal to be sent\n"); 64691.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64701.1Skamil 64711.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 64721.1Skamil "SIGTRAP\n", TWAIT_FNAME); 64731.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64741.1Skamil 64751.1Skamil validate_status_stopped(status, SIGTRAP); 64761.1Skamil 64771.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 64781.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 64791.1Skamil 64801.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 64811.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 64821.1Skamil 64831.1Skamil PARENT_FROM_CHILD("Message", fds, msg); 64841.1Skamil 64851.13Schristos DPRINTF("Before resuming the child process where it left off and " 64861.1Skamil "without signal to be sent\n"); 64871.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64881.1Skamil 64891.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 64901.1Skamil "SIGINT\n", TWAIT_FNAME); 64911.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64921.1Skamil 64931.1Skamil validate_status_stopped(status, SIGINT); 64941.1Skamil 64951.1Skamil pl.pl_lwpid = 0; 64961.1Skamil 64971.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 64981.1Skamil while (pl.pl_lwpid != 0) { 64991.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 65001.1Skamil switch (pl.pl_lwpid) { 65011.1Skamil case 1: 65021.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 65031.1Skamil break; 65041.1Skamil case 2: 65051.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 65061.1Skamil break; 65071.1Skamil } 65081.1Skamil } 65091.1Skamil 65101.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 65111.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 65121.1Skamil 65131.13Schristos DPRINTF("Before resuming the child process where it left off and " 65141.1Skamil "without signal to be sent\n"); 65151.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65161.1Skamil 65171.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 65181.1Skamil TWAIT_FNAME); 65191.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65201.1Skamil 65211.1Skamil validate_status_exited(status, exitval); 65221.1Skamil 65231.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 65241.1Skamil TWAIT_FNAME); 65251.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 65261.1Skamil 65271.1Skamil msg_close(&fds); 65281.1Skamil} 65291.1Skamil 65301.1SkamilATF_TC(syscall1); 65311.1SkamilATF_TC_HEAD(syscall1, tc) 65321.1Skamil{ 65331.1Skamil atf_tc_set_md_var(tc, "descr", 65341.1Skamil "Verify that getpid(2) can be traced with PT_SYSCALL"); 65351.1Skamil} 65361.1Skamil 65371.1SkamilATF_TC_BODY(syscall1, tc) 65381.1Skamil{ 65391.1Skamil const int exitval = 5; 65401.1Skamil const int sigval = SIGSTOP; 65411.1Skamil pid_t child, wpid; 65421.1Skamil#if defined(TWAIT_HAVE_STATUS) 65431.1Skamil int status; 65441.1Skamil#endif 65451.1Skamil struct ptrace_siginfo info; 65461.1Skamil memset(&info, 0, sizeof(info)); 65471.1Skamil 65481.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 65491.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 65501.1Skamil if (child == 0) { 65511.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 65521.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 65531.1Skamil 65541.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 65551.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 65561.1Skamil 65571.1Skamil syscall(SYS_getpid); 65581.1Skamil 65591.13Schristos DPRINTF("Before exiting of the child process\n"); 65601.1Skamil _exit(exitval); 65611.1Skamil } 65621.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 65631.1Skamil 65641.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65651.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65661.1Skamil 65671.1Skamil validate_status_stopped(status, sigval); 65681.1Skamil 65691.13Schristos DPRINTF("Before resuming the child process where it left off and " 65701.1Skamil "without signal to be sent\n"); 65711.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 65721.1Skamil 65731.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65741.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65751.1Skamil 65761.1Skamil validate_status_stopped(status, SIGTRAP); 65771.1Skamil 65781.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 65791.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 65801.1Skamil 65811.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 65821.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 65831.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 65841.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE); 65851.1Skamil 65861.13Schristos DPRINTF("Before resuming the child process where it left off and " 65871.1Skamil "without signal to be sent\n"); 65881.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 65891.1Skamil 65901.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65911.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65921.1Skamil 65931.1Skamil validate_status_stopped(status, SIGTRAP); 65941.1Skamil 65951.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 65961.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 65971.1Skamil 65981.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 65991.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 66001.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 66011.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX); 66021.1Skamil 66031.13Schristos DPRINTF("Before resuming the child process where it left off and " 66041.1Skamil "without signal to be sent\n"); 66051.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66061.1Skamil 66071.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66081.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66091.1Skamil 66101.1Skamil validate_status_exited(status, exitval); 66111.1Skamil 66121.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66131.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 66141.1Skamil} 66151.1Skamil 66161.1SkamilATF_TC(syscallemu1); 66171.1SkamilATF_TC_HEAD(syscallemu1, tc) 66181.1Skamil{ 66191.1Skamil atf_tc_set_md_var(tc, "descr", 66201.1Skamil "Verify that exit(2) can be intercepted with PT_SYSCALLEMU"); 66211.1Skamil} 66221.1Skamil 66231.1SkamilATF_TC_BODY(syscallemu1, tc) 66241.1Skamil{ 66251.1Skamil const int exitval = 5; 66261.1Skamil const int sigval = SIGSTOP; 66271.1Skamil pid_t child, wpid; 66281.1Skamil#if defined(TWAIT_HAVE_STATUS) 66291.1Skamil int status; 66301.1Skamil#endif 66311.1Skamil 66321.6Skamil#if defined(__sparc__) && !defined(__sparc64__) 66331.6Skamil /* syscallemu does not work on sparc (32-bit) */ 66341.6Skamil atf_tc_expect_fail("PR kern/52166"); 66351.6Skamil#endif 66361.6Skamil 66371.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 66381.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 66391.1Skamil if (child == 0) { 66401.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 66411.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 66421.1Skamil 66431.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 66441.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 66451.1Skamil 66461.1Skamil syscall(SYS_exit, 100); 66471.1Skamil 66481.13Schristos DPRINTF("Before exiting of the child process\n"); 66491.1Skamil _exit(exitval); 66501.1Skamil } 66511.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 66521.1Skamil 66531.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66541.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66551.1Skamil 66561.1Skamil validate_status_stopped(status, sigval); 66571.1Skamil 66581.13Schristos DPRINTF("Before resuming the child process where it left off and " 66591.1Skamil "without signal to be sent\n"); 66601.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 66611.1Skamil 66621.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66631.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66641.1Skamil 66651.1Skamil validate_status_stopped(status, SIGTRAP); 66661.1Skamil 66671.13Schristos DPRINTF("Set SYSCALLEMU for intercepted syscall\n"); 66681.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1); 66691.1Skamil 66701.13Schristos DPRINTF("Before resuming the child process where it left off and " 66711.1Skamil "without signal to be sent\n"); 66721.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 66731.1Skamil 66741.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66751.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66761.1Skamil 66771.1Skamil validate_status_stopped(status, SIGTRAP); 66781.1Skamil 66791.13Schristos DPRINTF("Before resuming the child process where it left off and " 66801.1Skamil "without signal to be sent\n"); 66811.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66821.1Skamil 66831.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66841.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66851.1Skamil 66861.1Skamil validate_status_exited(status, exitval); 66871.1Skamil 66881.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66891.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 66901.1Skamil} 66911.1Skamil 66921.103Skamil/// ---------------------------------------------------------------------------- 66931.103Skamil 66941.106Skamilstatic void 66951.106Skamilclone_body(int flags, bool trackfork, bool trackvfork, 66961.106Skamil bool trackvforkdone) 66971.106Skamil{ 66981.106Skamil const int exitval = 5; 66991.106Skamil const int exitval2 = 15; 67001.106Skamil const int sigval = SIGSTOP; 67011.106Skamil pid_t child, child2 = 0, wpid; 67021.106Skamil#if defined(TWAIT_HAVE_STATUS) 67031.106Skamil int status; 67041.106Skamil#endif 67051.106Skamil ptrace_state_t state; 67061.106Skamil const int slen = sizeof(state); 67071.106Skamil ptrace_event_t event; 67081.106Skamil const int elen = sizeof(event); 67091.106Skamil 67101.106Skamil const size_t stack_size = 1024 * 1024; 67111.106Skamil void *stack, *stack_base; 67121.106Skamil 67131.106Skamil stack = malloc(stack_size); 67141.106Skamil ATF_REQUIRE(stack != NULL); 67151.106Skamil 67161.106Skamil#ifdef __MACHINE_STACK_GROWS_UP 67171.106Skamil stack_base = stack; 67181.106Skamil#else 67191.106Skamil stack_base = (char *)stack + stack_size; 67201.106Skamil#endif 67211.106Skamil 67221.106Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 67231.106Skamil SYSCALL_REQUIRE((child = fork()) != -1); 67241.106Skamil if (child == 0) { 67251.106Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 67261.106Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 67271.106Skamil 67281.106Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 67291.106Skamil FORKEE_ASSERT(raise(sigval) == 0); 67301.106Skamil 67311.106Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 67321.106Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 67331.106Skamil 67341.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 67351.106Skamil child2); 67361.106Skamil 67371.106Skamil // XXX WALLSIG? 67381.106Skamil FORKEE_REQUIRE_SUCCESS 67391.106Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 67401.106Skamil 67411.106Skamil forkee_status_exited(status, exitval2); 67421.106Skamil 67431.106Skamil DPRINTF("Before exiting of the child process\n"); 67441.106Skamil _exit(exitval); 67451.106Skamil } 67461.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 67471.106Skamil 67481.106Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67491.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67501.106Skamil 67511.106Skamil validate_status_stopped(status, sigval); 67521.106Skamil 67531.106Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 67541.106Skamil trackfork ? "|PTRACE_FORK" : "", 67551.106Skamil trackvfork ? "|PTRACE_VFORK" : "", 67561.106Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 67571.106Skamil event.pe_set_event = 0; 67581.106Skamil if (trackfork) 67591.106Skamil event.pe_set_event |= PTRACE_FORK; 67601.106Skamil if (trackvfork) 67611.106Skamil event.pe_set_event |= PTRACE_VFORK; 67621.106Skamil if (trackvforkdone) 67631.106Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 67641.106Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 67651.106Skamil 67661.106Skamil DPRINTF("Before resuming the child process where it left off and " 67671.106Skamil "without signal to be sent\n"); 67681.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 67691.106Skamil 67701.106Skamil#if defined(TWAIT_HAVE_PID) 67711.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 67721.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 67731.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 67741.106Skamil child); 67751.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 67761.106Skamil child); 67771.106Skamil 67781.106Skamil validate_status_stopped(status, SIGTRAP); 67791.106Skamil 67801.106Skamil SYSCALL_REQUIRE( 67811.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 67821.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 67831.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 67841.106Skamil PTRACE_FORK); 67851.106Skamil } 67861.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 67871.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 67881.106Skamil PTRACE_VFORK); 67891.106Skamil } 67901.106Skamil 67911.106Skamil child2 = state.pe_other_pid; 67921.106Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 67931.106Skamil 67941.106Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 67951.106Skamil "%d\n", TWAIT_FNAME, child2, child); 67961.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 67971.106Skamil child2); 67981.106Skamil 67991.106Skamil validate_status_stopped(status, SIGTRAP); 68001.106Skamil 68011.106Skamil SYSCALL_REQUIRE( 68021.106Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 68031.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 68041.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 68051.106Skamil PTRACE_FORK); 68061.106Skamil } 68071.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 68081.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 68091.106Skamil PTRACE_VFORK); 68101.106Skamil } 68111.106Skamil 68121.106Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 68131.106Skamil 68141.106Skamil DPRINTF("Before resuming the forkee process where it left off " 68151.106Skamil "and without signal to be sent\n"); 68161.106Skamil SYSCALL_REQUIRE( 68171.106Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 68181.106Skamil 68191.106Skamil DPRINTF("Before resuming the child process where it left off " 68201.106Skamil "and without signal to be sent\n"); 68211.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68221.106Skamil } 68231.106Skamil#endif 68241.106Skamil 68251.106Skamil if (trackvforkdone && (flags & CLONE_VFORK)) { 68261.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 68271.106Skamil child); 68281.106Skamil TWAIT_REQUIRE_SUCCESS( 68291.106Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 68301.106Skamil 68311.106Skamil validate_status_stopped(status, SIGTRAP); 68321.106Skamil 68331.106Skamil SYSCALL_REQUIRE( 68341.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 68351.106Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 68361.106Skamil 68371.106Skamil child2 = state.pe_other_pid; 68381.106Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 68391.106Skamil child2); 68401.106Skamil 68411.106Skamil DPRINTF("Before resuming the child process where it left off " 68421.106Skamil "and without signal to be sent\n"); 68431.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68441.106Skamil } 68451.106Skamil 68461.103Skamil#if defined(TWAIT_HAVE_PID) 68471.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 68481.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 68491.106Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 68501.106Skamil "\n", TWAIT_FNAME); 68511.106Skamil TWAIT_REQUIRE_SUCCESS( 68521.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 68531.106Skamil 68541.106Skamil validate_status_exited(status, exitval2); 68551.106Skamil 68561.106Skamil DPRINTF("Before calling %s() for the forkee - expected no " 68571.106Skamil "process\n", TWAIT_FNAME); 68581.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 68591.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 68601.106Skamil } 68611.106Skamil#endif 68621.106Skamil 68631.106Skamil DPRINTF("Before calling %s() for the child - expected stopped " 68641.106Skamil "SIGCHLD\n", TWAIT_FNAME); 68651.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68661.106Skamil 68671.106Skamil validate_status_stopped(status, SIGCHLD); 68681.106Skamil 68691.106Skamil DPRINTF("Before resuming the child process where it left off and " 68701.106Skamil "without signal to be sent\n"); 68711.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68721.106Skamil 68731.106Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 68741.106Skamil TWAIT_FNAME); 68751.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68761.106Skamil 68771.106Skamil validate_status_exited(status, exitval); 68781.103Skamil 68791.106Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 68801.106Skamil TWAIT_FNAME); 68811.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 68821.106Skamil} 68831.103Skamil 68841.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone) \ 68851.106SkamilATF_TC(name); \ 68861.106SkamilATF_TC_HEAD(name, tc) \ 68871.106Skamil{ \ 68881.106Skamil atf_tc_set_md_var(tc, "descr", "Verify clone(%s) " \ 68891.106Skamil "called with 0%s%s%s in EVENT_MASK", \ 68901.106Skamil #flags, \ 68911.106Skamil tfork ? "|PTRACE_FORK" : "", \ 68921.106Skamil tvfork ? "|PTRACE_VFORK" : "", \ 68931.106Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 68941.106Skamil} \ 68951.106Skamil \ 68961.106SkamilATF_TC_BODY(name, tc) \ 68971.106Skamil{ \ 68981.106Skamil \ 68991.106Skamil clone_body(flags, tfork, tvfork, tvforkdone); \ 69001.103Skamil} 69011.103Skamil 69021.106SkamilCLONE_TEST(clone1, 0, false, false, false) 69031.106Skamil#if defined(TWAIT_HAVE_PID) 69041.106SkamilCLONE_TEST(clone2, 0, true, false, false) 69051.106SkamilCLONE_TEST(clone3, 0, false, true, false) 69061.106SkamilCLONE_TEST(clone4, 0, true, true, false) 69071.106Skamil#endif 69081.106SkamilCLONE_TEST(clone5, 0, false, false, true) 69091.106Skamil#if defined(TWAIT_HAVE_PID) 69101.106SkamilCLONE_TEST(clone6, 0, true, false, true) 69111.106SkamilCLONE_TEST(clone7, 0, false, true, true) 69121.106SkamilCLONE_TEST(clone8, 0, true, true, true) 69131.106Skamil#endif 69141.106Skamil 69151.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false) 69161.106Skamil#if defined(TWAIT_HAVE_PID) 69171.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false) 69181.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false) 69191.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false) 69201.106Skamil#endif 69211.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true) 69221.106Skamil#if defined(TWAIT_HAVE_PID) 69231.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true) 69241.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true) 69251.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true) 69261.106Skamil#endif 69271.106Skamil 69281.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false) 69291.106Skamil#if defined(TWAIT_HAVE_PID) 69301.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false) 69311.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false) 69321.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false) 69331.106Skamil#endif 69341.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true) 69351.106Skamil#if defined(TWAIT_HAVE_PID) 69361.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true) 69371.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true) 69381.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true) 69391.106Skamil#endif 69401.106Skamil 69411.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false) 69421.106Skamil#if defined(TWAIT_HAVE_PID) 69431.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false) 69441.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false) 69451.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false) 69461.106Skamil#endif 69471.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true) 69481.106Skamil#if defined(TWAIT_HAVE_PID) 69491.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true) 69501.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true) 69511.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true) 69521.106Skamil#endif 69531.106Skamil 69541.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false) 69551.106Skamil#if defined(TWAIT_HAVE_PID) 69561.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false) 69571.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false) 69581.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false) 69591.106Skamil#endif 69601.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true) 69611.106Skamil#if defined(TWAIT_HAVE_PID) 69621.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true) 69631.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true) 69641.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true) 69651.106Skamil#endif 69661.106Skamil 69671.110Skamil#if TEST_VFORK_ENABLED 69681.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false) 69691.106Skamil#if defined(TWAIT_HAVE_PID) 69701.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false) 69711.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false) 69721.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false) 69731.106Skamil#endif 69741.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true) 69751.106Skamil#if defined(TWAIT_HAVE_PID) 69761.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true) 69771.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true) 69781.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true) 69791.106Skamil#endif 69801.110Skamil#endif 69811.106Skamil 69821.106Skamil/// ---------------------------------------------------------------------------- 69831.106Skamil 69841.106Skamil#if defined(TWAIT_HAVE_PID) 69851.103Skamilstatic void 69861.106Skamilclone_body2(int flags, bool masked, bool ignored) 69871.103Skamil{ 69881.103Skamil const int exitval = 5; 69891.103Skamil const int exitval2 = 15; 69901.103Skamil const int sigval = SIGSTOP; 69911.103Skamil pid_t child, child2 = 0, wpid; 69921.103Skamil#if defined(TWAIT_HAVE_STATUS) 69931.103Skamil int status; 69941.103Skamil#endif 69951.103Skamil ptrace_state_t state; 69961.103Skamil const int slen = sizeof(state); 69971.103Skamil ptrace_event_t event; 69981.103Skamil const int elen = sizeof(event); 69991.103Skamil struct sigaction sa; 70001.103Skamil struct ptrace_siginfo info; 70011.103Skamil sigset_t intmask; 70021.103Skamil struct kinfo_proc2 kp; 70031.103Skamil size_t len = sizeof(kp); 70041.103Skamil 70051.103Skamil int name[6]; 70061.103Skamil const size_t namelen = __arraycount(name); 70071.103Skamil ki_sigset_t kp_sigmask; 70081.103Skamil ki_sigset_t kp_sigignore; 70091.103Skamil 70101.103Skamil const size_t stack_size = 1024 * 1024; 70111.103Skamil void *stack, *stack_base; 70121.103Skamil 70131.103Skamil stack = malloc(stack_size); 70141.103Skamil ATF_REQUIRE(stack != NULL); 70151.103Skamil 70161.103Skamil#ifdef __MACHINE_STACK_GROWS_UP 70171.103Skamil stack_base = stack; 70181.103Skamil#else 70191.103Skamil stack_base = (char *)stack + stack_size; 70201.103Skamil#endif 70211.103Skamil 70221.103Skamil SYSCALL_REQUIRE((child = fork()) != -1); 70231.103Skamil if (child == 0) { 70241.103Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 70251.103Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 70261.103Skamil 70271.103Skamil if (masked) { 70281.103Skamil sigemptyset(&intmask); 70291.103Skamil sigaddset(&intmask, SIGTRAP); 70301.103Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 70311.103Skamil } 70321.103Skamil 70331.103Skamil if (ignored) { 70341.103Skamil memset(&sa, 0, sizeof(sa)); 70351.103Skamil sa.sa_handler = SIG_IGN; 70361.103Skamil sigemptyset(&sa.sa_mask); 70371.103Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 70381.103Skamil } 70391.103Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 70401.103Skamil FORKEE_ASSERT(raise(sigval) == 0); 70411.103Skamil 70421.103Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 70431.103Skamil flags); 70441.103Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 70451.103Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 70461.103Skamil 70471.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 70481.103Skamil child2); 70491.103Skamil 70501.103Skamil // XXX WALLSIG? 70511.103Skamil FORKEE_REQUIRE_SUCCESS 70521.103Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 70531.103Skamil 70541.103Skamil forkee_status_exited(status, exitval2); 70551.103Skamil 70561.103Skamil DPRINTF("Before exiting of the child process\n"); 70571.103Skamil _exit(exitval); 70581.103Skamil } 70591.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 70601.103Skamil 70611.103Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 70621.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 70631.103Skamil 70641.103Skamil validate_status_stopped(status, sigval); 70651.103Skamil 70661.103Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 70671.103Skamil SYSCALL_REQUIRE( 70681.103Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 70691.103Skamil 70701.103Skamil DPRINTF("Before checking siginfo_t\n"); 70711.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 70721.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 70731.103Skamil 70741.103Skamil name[0] = CTL_KERN, 70751.103Skamil name[1] = KERN_PROC2, 70761.103Skamil name[2] = KERN_PROC_PID; 70771.103Skamil name[3] = child; 70781.103Skamil name[4] = sizeof(kp); 70791.103Skamil name[5] = 1; 70801.103Skamil 70811.103Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 70821.103Skamil 70831.103Skamil if (masked) 70841.103Skamil kp_sigmask = kp.p_sigmask; 70851.103Skamil 70861.103Skamil if (ignored) 70871.103Skamil kp_sigignore = kp.p_sigignore; 70881.103Skamil 70891.103Skamil DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in " 70901.103Skamil "EVENT_MASK for the child %d\n", child); 70911.103Skamil event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE; 70921.103Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 70931.103Skamil 70941.103Skamil DPRINTF("Before resuming the child process where it left off and " 70951.103Skamil "without signal to be sent\n"); 70961.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 70971.103Skamil 70981.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 70991.103Skamil child); 71001.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 71011.103Skamil child); 71021.103Skamil 71031.103Skamil validate_status_stopped(status, SIGTRAP); 71041.103Skamil 71051.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 71061.103Skamil 71071.103Skamil if (masked) { 71081.103Skamil DPRINTF("kp_sigmask=" 71091.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71101.103Skamil PRIx32 "\n", 71111.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 71121.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 71131.103Skamil 71141.103Skamil DPRINTF("kp.p_sigmask=" 71151.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71161.103Skamil PRIx32 "\n", 71171.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 71181.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 71191.103Skamil 71201.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 71211.103Skamil sizeof(kp_sigmask))); 71221.103Skamil } 71231.103Skamil 71241.103Skamil if (ignored) { 71251.103Skamil DPRINTF("kp_sigignore=" 71261.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71271.103Skamil PRIx32 "\n", 71281.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 71291.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 71301.103Skamil 71311.103Skamil DPRINTF("kp.p_sigignore=" 71321.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71331.103Skamil PRIx32 "\n", 71341.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 71351.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 71361.103Skamil 71371.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 71381.103Skamil sizeof(kp_sigignore))); 71391.103Skamil } 71401.103Skamil 71411.103Skamil SYSCALL_REQUIRE( 71421.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 71431.103Skamil DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event, 71441.103Skamil child2); 71451.103Skamil if (!(flags & CLONE_VFORK)) { 71461.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 71471.103Skamil PTRACE_FORK); 71481.103Skamil } else { 71491.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 71501.103Skamil PTRACE_VFORK); 71511.103Skamil } 71521.103Skamil 71531.103Skamil child2 = state.pe_other_pid; 71541.103Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 71551.103Skamil 71561.103Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 71571.103Skamil "%d\n", TWAIT_FNAME, child2, child); 71581.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 71591.103Skamil child2); 71601.103Skamil 71611.103Skamil validate_status_stopped(status, SIGTRAP); 71621.103Skamil 71631.103Skamil name[3] = child2; 71641.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 71651.103Skamil 71661.103Skamil if (masked) { 71671.103Skamil DPRINTF("kp_sigmask=" 71681.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71691.103Skamil PRIx32 "\n", 71701.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 71711.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 71721.103Skamil 71731.103Skamil DPRINTF("kp.p_sigmask=" 71741.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71751.103Skamil PRIx32 "\n", 71761.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 71771.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 71781.103Skamil 71791.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 71801.103Skamil sizeof(kp_sigmask))); 71811.103Skamil } 71821.103Skamil 71831.103Skamil if (ignored) { 71841.103Skamil DPRINTF("kp_sigignore=" 71851.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71861.103Skamil PRIx32 "\n", 71871.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 71881.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 71891.103Skamil 71901.103Skamil DPRINTF("kp.p_sigignore=" 71911.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71921.103Skamil PRIx32 "\n", 71931.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 71941.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 71951.103Skamil 71961.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 71971.103Skamil sizeof(kp_sigignore))); 71981.103Skamil } 71991.103Skamil 72001.103Skamil SYSCALL_REQUIRE( 72011.103Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 72021.103Skamil if (!(flags & CLONE_VFORK)) { 72031.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 72041.103Skamil PTRACE_FORK); 72051.103Skamil } else { 72061.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 72071.103Skamil PTRACE_VFORK); 72081.103Skamil } 72091.103Skamil 72101.103Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 72111.103Skamil 72121.103Skamil DPRINTF("Before resuming the forkee process where it left off " 72131.103Skamil "and without signal to be sent\n"); 72141.103Skamil SYSCALL_REQUIRE( 72151.103Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 72161.103Skamil 72171.103Skamil DPRINTF("Before resuming the child process where it left off " 72181.103Skamil "and without signal to be sent\n"); 72191.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 72201.103Skamil 72211.103Skamil if (flags & CLONE_VFORK) { 72221.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 72231.103Skamil child); 72241.103Skamil TWAIT_REQUIRE_SUCCESS( 72251.103Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 72261.103Skamil 72271.103Skamil validate_status_stopped(status, SIGTRAP); 72281.103Skamil 72291.103Skamil name[3] = child; 72301.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 72311.103Skamil 72321.103Skamil /* 72331.103Skamil * SIGCHLD is now pending in the signal queue and 72341.103Skamil * the kernel presents it to userland as a masked signal. 72351.103Skamil */ 72361.103Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 72371.103Skamil 72381.103Skamil if (masked) { 72391.103Skamil DPRINTF("kp_sigmask=" 72401.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72411.103Skamil PRIx32 "\n", 72421.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 72431.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 72441.103Skamil 72451.103Skamil DPRINTF("kp.p_sigmask=" 72461.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72471.103Skamil PRIx32 "\n", 72481.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 72491.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 72501.103Skamil 72511.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 72521.103Skamil sizeof(kp_sigmask))); 72531.103Skamil } 72541.103Skamil 72551.103Skamil if (ignored) { 72561.103Skamil DPRINTF("kp_sigignore=" 72571.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72581.103Skamil PRIx32 "\n", 72591.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 72601.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 72611.103Skamil 72621.103Skamil DPRINTF("kp.p_sigignore=" 72631.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72641.103Skamil PRIx32 "\n", 72651.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 72661.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 72671.103Skamil 72681.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 72691.103Skamil sizeof(kp_sigignore))); 72701.103Skamil } 72711.103Skamil 72721.103Skamil SYSCALL_REQUIRE( 72731.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 72741.103Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 72751.103Skamil 72761.103Skamil child2 = state.pe_other_pid; 72771.103Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 72781.103Skamil child2); 72791.103Skamil 72801.103Skamil DPRINTF("Before resuming the child process where it left off " 72811.103Skamil "and without signal to be sent\n"); 72821.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 72831.103Skamil } 72841.103Skamil 72851.103Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 72861.103Skamil "\n", TWAIT_FNAME); 72871.103Skamil TWAIT_REQUIRE_SUCCESS( 72881.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 72891.103Skamil 72901.103Skamil validate_status_exited(status, exitval2); 72911.103Skamil 72921.103Skamil DPRINTF("Before calling %s() for the forkee - expected no " 72931.103Skamil "process\n", TWAIT_FNAME); 72941.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 72951.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 72961.103Skamil 72971.103Skamil DPRINTF("Before calling %s() for the child - expected stopped " 72981.103Skamil "SIGCHLD\n", TWAIT_FNAME); 72991.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 73001.103Skamil 73011.103Skamil validate_status_stopped(status, SIGCHLD); 73021.103Skamil 73031.103Skamil DPRINTF("Before resuming the child process where it left off and " 73041.103Skamil "without signal to be sent\n"); 73051.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 73061.103Skamil 73071.103Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 73081.103Skamil TWAIT_FNAME); 73091.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 73101.103Skamil 73111.103Skamil validate_status_exited(status, exitval); 73121.103Skamil 73131.103Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 73141.103Skamil TWAIT_FNAME); 73151.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 73161.103Skamil} 73171.103Skamil 73181.106Skamil#define CLONE_TEST2(name,flags,masked,ignored) \ 73191.103SkamilATF_TC(name); \ 73201.103SkamilATF_TC_HEAD(name, tc) \ 73211.103Skamil{ \ 73221.103Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\ 73231.103Skamil " regardless of signal %s%s", \ 73241.103Skamil #flags, masked ? "masked" : "", ignored ? "ignored" : ""); \ 73251.103Skamil} \ 73261.103Skamil \ 73271.103SkamilATF_TC_BODY(name, tc) \ 73281.103Skamil{ \ 73291.103Skamil \ 73301.106Skamil clone_body2(flags, masked, ignored); \ 73311.103Skamil} 73321.103Skamil 73331.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false) 73341.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true) 73351.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false) 73361.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true) 73371.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false) 73381.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true) 73391.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false) 73401.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true) 73411.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX 73421.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true) // XXX 73431.110Skamil#if TEST_VFORK_ENABLED 73441.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false) 73451.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true) 73461.103Skamil#endif 73471.110Skamil#endif 73481.103Skamil 73491.103Skamil/// ---------------------------------------------------------------------------- 73501.103Skamil 73511.111Skamil#if TEST_VFORK_ENABLED 73521.107Skamil#if defined(TWAIT_HAVE_PID) 73531.107Skamilstatic void 73541.107Skamiltraceme_vfork_clone_body(int flags) 73551.107Skamil{ 73561.107Skamil const int exitval = 5; 73571.107Skamil const int exitval2 = 15; 73581.107Skamil pid_t child, child2 = 0, wpid; 73591.107Skamil#if defined(TWAIT_HAVE_STATUS) 73601.107Skamil int status; 73611.107Skamil#endif 73621.107Skamil 73631.107Skamil const size_t stack_size = 1024 * 1024; 73641.107Skamil void *stack, *stack_base; 73651.107Skamil 73661.107Skamil stack = malloc(stack_size); 73671.107Skamil ATF_REQUIRE(stack != NULL); 73681.107Skamil 73691.107Skamil#ifdef __MACHINE_STACK_GROWS_UP 73701.107Skamil stack_base = stack; 73711.107Skamil#else 73721.107Skamil stack_base = (char *)stack + stack_size; 73731.107Skamil#endif 73741.107Skamil 73751.107Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 73761.107Skamil if (child == 0) { 73771.107Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 73781.107Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 73791.107Skamil 73801.107Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 73811.107Skamil flags); 73821.107Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 73831.107Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 73841.107Skamil 73851.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 73861.107Skamil child2); 73871.107Skamil 73881.107Skamil // XXX WALLSIG? 73891.107Skamil FORKEE_REQUIRE_SUCCESS 73901.107Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 73911.107Skamil 73921.107Skamil forkee_status_exited(status, exitval2); 73931.107Skamil 73941.107Skamil DPRINTF("Before exiting of the child process\n"); 73951.107Skamil _exit(exitval); 73961.107Skamil } 73971.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 73981.107Skamil 73991.107Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 74001.107Skamil TWAIT_FNAME); 74011.107Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74021.107Skamil 74031.107Skamil validate_status_exited(status, exitval); 74041.107Skamil 74051.107Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 74061.107Skamil TWAIT_FNAME); 74071.107Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 74081.107Skamil} 74091.107Skamil 74101.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags) \ 74111.107SkamilATF_TC(name); \ 74121.107SkamilATF_TC_HEAD(name, tc) \ 74131.107Skamil{ \ 74141.107Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is " \ 74151.107Skamil "handled correctly with vfork(2)ed tracer", \ 74161.107Skamil #flags); \ 74171.107Skamil} \ 74181.107Skamil \ 74191.107SkamilATF_TC_BODY(name, tc) \ 74201.107Skamil{ \ 74211.107Skamil \ 74221.107Skamil traceme_vfork_clone_body(flags); \ 74231.107Skamil} 74241.107Skamil 74251.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0) 74261.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM) 74271.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS) 74281.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES) 74291.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND) // XXX 74301.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK) 74311.107Skamil#endif 74321.110Skamil#endif 74331.107Skamil 74341.107Skamil/// ---------------------------------------------------------------------------- 74351.107Skamil 74361.1Skamil#include "t_ptrace_amd64_wait.h" 74371.1Skamil#include "t_ptrace_i386_wait.h" 74381.1Skamil#include "t_ptrace_x86_wait.h" 74391.1Skamil 74401.1SkamilATF_TP_ADD_TCS(tp) 74411.1Skamil{ 74421.1Skamil setvbuf(stdout, NULL, _IONBF, 0); 74431.1Skamil setvbuf(stderr, NULL, _IONBF, 0); 74441.33Skamil 74451.36Skamil ATF_TP_ADD_TC(tp, traceme_raise1); 74461.33Skamil ATF_TP_ADD_TC(tp, traceme_raise2); 74471.33Skamil ATF_TP_ADD_TC(tp, traceme_raise3); 74481.33Skamil ATF_TP_ADD_TC(tp, traceme_raise4); 74491.33Skamil ATF_TP_ADD_TC(tp, traceme_raise5); 74501.85Skamil ATF_TP_ADD_TC(tp, traceme_raise6); 74511.85Skamil ATF_TP_ADD_TC(tp, traceme_raise7); 74521.85Skamil ATF_TP_ADD_TC(tp, traceme_raise8); 74531.85Skamil ATF_TP_ADD_TC(tp, traceme_raise9); 74541.85Skamil ATF_TP_ADD_TC(tp, traceme_raise10); 74551.33Skamil 74561.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1); 74571.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2); 74581.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3); 74591.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4); 74601.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5); 74611.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6); 74621.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7); 74631.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8); 74641.87Skamil 74651.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1); 74661.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2); 74671.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3); 74681.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4); 74691.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5); 74701.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6); 74711.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7); 74721.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8); 74731.86Skamil 74741.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_trap); 74751.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_segv); 74761.71Skamil ATF_TP_ADD_TC(tp, traceme_crash_ill); 74771.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_fpe); 74781.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_bus); 74791.59Skamil 74801.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap); 74811.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv); 74821.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill); 74831.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe); 74841.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus); 74851.88Skamil 74861.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap); 74871.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv); 74881.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill); 74891.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe); 74901.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus); 74911.88Skamil 74921.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1); 74931.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2); 74941.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3); 74951.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4); 74961.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5); 74971.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6); 74981.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7); 74991.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8); 75001.50Skamil 75011.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1); 75021.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2); 75031.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3); 75041.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4); 75051.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5); 75061.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6); 75071.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7); 75081.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8); 75091.50Skamil 75101.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1); 75111.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2); 75121.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3); 75131.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4); 75141.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5); 75151.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6); 75161.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7); 75171.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8); 75181.50Skamil 75191.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1); 75201.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2); 75211.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3); 75221.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4); 75231.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5); 75241.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6); 75251.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7); 75261.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8); 75271.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9); 75281.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10); 75291.1Skamil 75301.37Skamil ATF_TP_ADD_TC(tp, traceme_pid1_parent); 75311.37Skamil 75321.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise1); 75331.46Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise2); 75341.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise3); 75351.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise4); 75361.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise5); 75371.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise6); 75381.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise7); 75391.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise8); 75401.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise9); 75411.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise10); 75421.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise11); 75431.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise12); 75441.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise13); 75451.40Skamil 75461.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap); 75471.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv); 75481.71Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill); 75491.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe); 75501.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus); 75511.41Skamil 75521.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap); 75531.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv); 75541.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill); 75551.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe); 75561.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus); 75571.92Skamil 75581.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap); 75591.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv); 75601.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill); 75611.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe); 75621.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus); 75631.92Skamil 75641.43Skamil ATF_TP_ADD_TC(tp, traceme_vfork_exec); 75651.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec); 75661.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec); 75671.43Skamil 75681.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap); 75691.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv); 75701.71Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill); 75711.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe); 75721.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus); 75731.59Skamil 75741.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 75751.94Skamil unrelated_tracer_sees_signalmasked_crash_trap); 75761.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 75771.94Skamil unrelated_tracer_sees_signalmasked_crash_segv); 75781.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 75791.94Skamil unrelated_tracer_sees_signalmasked_crash_ill); 75801.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 75811.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe); 75821.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 75831.94Skamil unrelated_tracer_sees_signalmasked_crash_bus); 75841.94Skamil 75851.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 75861.94Skamil unrelated_tracer_sees_signalignored_crash_trap); 75871.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 75881.94Skamil unrelated_tracer_sees_signalignored_crash_segv); 75891.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 75901.94Skamil unrelated_tracer_sees_signalignored_crash_ill); 75911.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 75921.94Skamil unrelated_tracer_sees_signalignored_crash_fpe); 75931.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 75941.94Skamil unrelated_tracer_sees_signalignored_crash_bus); 75951.94Skamil 75961.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent); 75971.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates); 75981.61Skre ATF_TP_ADD_TC_HAVE_PID(tp, 75991.61Skre unrelated_tracer_sees_terminaton_before_the_parent); 76001.67Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process); 76011.51Skamil 76021.51Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_child); 76031.66Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child); 76041.51Skamil 76051.51Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_parent); 76061.65Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent); 76071.51Skamil 76081.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 76091.51Skamil tracee_sees_its_original_parent_getppid); 76101.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 76111.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2); 76121.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 76131.51Skamil tracee_sees_its_original_parent_procfs_status); 76141.1Skamil 76151.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_empty); 76161.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_fork); 76171.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork); 76181.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done); 76191.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create); 76201.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit); 76211.1Skamil 76221.31Skamil ATF_TP_ADD_TC(tp, fork1); 76231.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork2); 76241.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork3); 76251.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork4); 76261.31Skamil ATF_TP_ADD_TC(tp, fork5); 76271.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork6); 76281.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork7); 76291.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork8); 76301.31Skamil 76311.109Skamil#if TEST_VFORK_ENABLED 76321.31Skamil ATF_TP_ADD_TC(tp, vfork1); 76331.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork2); 76341.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork3); 76351.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork4); 76361.31Skamil ATF_TP_ADD_TC(tp, vfork5); 76371.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork6); 76381.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork7); 76391.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork8); 76401.116Skamil#endif 76411.1Skamil 76421.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_detach_forker); 76431.116Skamil#if TEST_VFORK_ENABLED 76441.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforker); 76451.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforkerdone); 76461.116Skamil#endif 76471.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_kill_forker); 76481.116Skamil#if TEST_VFORK_ENABLED 76491.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforker); 76501.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforkerdone); 76511.116Skamil#endif 76521.116Skamil 76531.116Skamil#if TEST_VFORK_ENABLED 76541.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_fork); 76551.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_vfork); 76561.109Skamil#endif 76571.108Skamil 76581.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8); 76591.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16); 76601.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32); 76611.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64); 76621.54Skamil 76631.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8); 76641.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16); 76651.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32); 76661.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64); 76671.54Skamil 76681.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8); 76691.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16); 76701.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32); 76711.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64); 76721.54Skamil 76731.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8); 76741.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16); 76751.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32); 76761.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64); 76771.54Skamil 76781.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d); 76791.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i); 76801.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d); 76811.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i); 76821.54Skamil 76831.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text); 76841.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text); 76851.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text); 76861.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text); 76871.54Skamil 76881.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text); 76891.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text); 76901.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text); 76911.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text); 76921.54Skamil 76931.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text); 76941.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text); 76951.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text); 76961.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text); 76971.54Skamil 76981.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text); 76991.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text); 77001.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text); 77011.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text); 77021.54Skamil 77031.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text); 77041.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text); 77051.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text); 77061.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text); 77071.1Skamil 77081.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv); 77091.1Skamil 77101.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i); 77111.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d); 77121.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i); 77131.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d); 77141.101Skamil 77151.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i); 77161.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d); 77171.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i); 77181.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d); 77191.101Skamil 77201.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv); 77211.101Skamil 77221.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i); 77231.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d); 77241.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i); 77251.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d); 77261.115Skamil 77271.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i); 77281.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d); 77291.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i); 77301.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d); 77311.115Skamil 77321.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1); 77331.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2); 77341.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3); 77351.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4); 77361.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5); 77371.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6); 77381.1Skamil 77391.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1); 77401.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2); 77411.1Skamil 77421.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step1); 77431.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step2); 77441.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step3); 77451.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step4); 77461.1Skamil 77471.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep1); 77481.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep2); 77491.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep3); 77501.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep4); 77511.2Skamil 77521.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked); 77531.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored); 77541.95Skamil 77551.1Skamil ATF_TP_ADD_TC(tp, kill1); 77561.1Skamil ATF_TP_ADD_TC(tp, kill2); 77571.75Skamil ATF_TP_ADD_TC(tp, kill3); 77581.1Skamil 77591.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0); 77601.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1); 77611.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2); 77621.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3); 77631.77Skamil 77641.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0); 77651.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1); 77661.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2); 77671.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3); 77681.1Skamil 77691.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_unmodified); 77701.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_faked); 77711.79Skamil 77721.82Skamil ATF_TP_ADD_TC(tp, traceme_exec); 77731.97Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_exec); 77741.97Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_exec); 77751.1Skamil 77761.119Skamil ATF_TP_ADD_TC(tp, trace_thread_nolwpevents); 77771.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpexit); 77781.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate); 77791.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit); 77801.1Skamil 77811.84Skamil ATF_TP_ADD_TC(tp, signal_mask_unrelated); 77821.84Skamil 77831.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked); 77841.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored); 77851.109Skamil#if TEST_VFORK_ENABLED 77861.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked); 77871.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored); 77881.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked); 77891.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored); 77901.109Skamil#endif 77911.99Skamil 77921.1Skamil ATF_TP_ADD_TC(tp, signal9); 77931.1Skamil ATF_TP_ADD_TC(tp, signal10); 77941.1Skamil 77951.1Skamil ATF_TP_ADD_TC(tp, suspend1); 77961.1Skamil ATF_TP_ADD_TC(tp, suspend2); 77971.1Skamil 77981.1Skamil ATF_TP_ADD_TC(tp, resume1); 77991.1Skamil 78001.1Skamil ATF_TP_ADD_TC(tp, syscall1); 78011.1Skamil 78021.1Skamil ATF_TP_ADD_TC(tp, syscallemu1); 78031.1Skamil 78041.106Skamil ATF_TP_ADD_TC(tp, clone1); 78051.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone2); 78061.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone3); 78071.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone4); 78081.106Skamil ATF_TP_ADD_TC(tp, clone5); 78091.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone6); 78101.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone7); 78111.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone8); 78121.106Skamil 78131.106Skamil ATF_TP_ADD_TC(tp, clone_vm1); 78141.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2); 78151.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3); 78161.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4); 78171.106Skamil ATF_TP_ADD_TC(tp, clone_vm5); 78181.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6); 78191.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7); 78201.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8); 78211.106Skamil 78221.106Skamil ATF_TP_ADD_TC(tp, clone_fs1); 78231.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2); 78241.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3); 78251.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4); 78261.106Skamil ATF_TP_ADD_TC(tp, clone_fs5); 78271.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6); 78281.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7); 78291.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8); 78301.106Skamil 78311.106Skamil ATF_TP_ADD_TC(tp, clone_files1); 78321.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2); 78331.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3); 78341.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4); 78351.106Skamil ATF_TP_ADD_TC(tp, clone_files5); 78361.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6); 78371.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7); 78381.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8); 78391.106Skamil 78401.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand1); // XXX 78411.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX 78421.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX 78431.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX 78441.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand5); // XXX 78451.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX 78461.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX 78471.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX 78481.106Skamil 78491.109Skamil#if TEST_VFORK_ENABLED 78501.106Skamil ATF_TP_ADD_TC(tp, clone_vfork1); 78511.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2); 78521.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3); 78531.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4); 78541.106Skamil ATF_TP_ADD_TC(tp, clone_vfork5); 78551.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6); 78561.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7); 78571.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8); 78581.109Skamil#endif 78591.106Skamil 78601.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored); 78611.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked); 78621.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored); 78631.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked); 78641.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored); 78651.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked); 78661.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored); 78671.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked); 78681.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX 78691.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX 78701.109Skamil#if TEST_VFORK_ENABLED 78711.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored); 78721.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked); 78731.109Skamil#endif 78741.103Skamil 78751.109Skamil#if TEST_VFORK_ENABLED 78761.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone); 78771.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm); 78781.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs); 78791.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files); 78801.107Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX 78811.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork); 78821.109Skamil#endif 78831.107Skamil 78841.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64(); 78851.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_I386(); 78861.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_X86(); 78871.1Skamil 78881.1Skamil return atf_no_error(); 78891.1Skamil} 7890