t_ptrace_wait.c revision 1.130
11.130Smgorny/* $NetBSD: t_ptrace_wait.c,v 1.130 2019/06/30 21:20:04 mgorny Exp $ */ 21.1Skamil 31.1Skamil/*- 41.78Skamil * Copyright (c) 2016, 2017, 2018, 2019 The NetBSD Foundation, Inc. 51.1Skamil * All rights reserved. 61.1Skamil * 71.1Skamil * Redistribution and use in source and binary forms, with or without 81.1Skamil * modification, are permitted provided that the following conditions 91.1Skamil * are met: 101.1Skamil * 1. Redistributions of source code must retain the above copyright 111.1Skamil * notice, this list of conditions and the following disclaimer. 121.1Skamil * 2. Redistributions in binary form must reproduce the above copyright 131.1Skamil * notice, this list of conditions and the following disclaimer in the 141.1Skamil * documentation and/or other materials provided with the distribution. 151.1Skamil * 161.1Skamil * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 171.1Skamil * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 181.1Skamil * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 191.1Skamil * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 201.1Skamil * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 211.1Skamil * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 221.1Skamil * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 231.1Skamil * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 241.1Skamil * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 251.1Skamil * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 261.1Skamil * POSSIBILITY OF SUCH DAMAGE. 271.1Skamil */ 281.1Skamil 291.1Skamil#include <sys/cdefs.h> 301.130Smgorny__RCSID("$NetBSD: t_ptrace_wait.c,v 1.130 2019/06/30 21:20:04 mgorny Exp $"); 311.1Skamil 321.1Skamil#include <sys/param.h> 331.1Skamil#include <sys/types.h> 341.130Smgorny#include <sys/exec_elf.h> 351.39Skamil#include <sys/mman.h> 361.1Skamil#include <sys/ptrace.h> 371.1Skamil#include <sys/resource.h> 381.1Skamil#include <sys/stat.h> 391.1Skamil#include <sys/syscall.h> 401.1Skamil#include <sys/sysctl.h> 411.129Smgorny#include <sys/uio.h> 421.1Skamil#include <sys/wait.h> 431.1Skamil#include <machine/reg.h> 441.1Skamil#include <elf.h> 451.1Skamil#include <err.h> 461.1Skamil#include <errno.h> 471.130Smgorny#include <fcntl.h> 481.1Skamil#include <lwp.h> 491.77Skamil#include <pthread.h> 501.1Skamil#include <sched.h> 511.1Skamil#include <signal.h> 521.124Skamil#include <spawn.h> 531.1Skamil#include <stdint.h> 541.1Skamil#include <stdio.h> 551.1Skamil#include <stdlib.h> 561.1Skamil#include <strings.h> 571.26Skamil#include <time.h> 581.1Skamil#include <unistd.h> 591.1Skamil 601.114Skamil#include <fenv.h> 611.114Skamil#if (__arm__ && !__SOFTFP__) || __aarch64__ 621.114Skamil#include <ieeefp.h> /* only need for ARM Cortex/Neon hack */ 631.114Skamil#endif 641.114Skamil 651.121Smgorny#if defined(__i386__) || defined(__x86_64__) 661.121Smgorny#include <cpuid.h> 671.121Smgorny#include <x86/cpu_extended_state.h> 681.129Smgorny#include <x86/specialreg.h> 691.121Smgorny#endif 701.121Smgorny 711.130Smgorny#include <libelf.h> 721.130Smgorny#include <gelf.h> 731.130Smgorny 741.1Skamil#include <atf-c.h> 751.1Skamil 761.1Skamil#include "h_macros.h" 771.1Skamil 781.1Skamil#include "t_ptrace_wait.h" 791.1Skamil#include "msg.h" 801.1Skamil 811.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \ 821.61Skre SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \ 831.61Skre sizeof(msg)) == 0) 841.1Skamil 851.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \ 861.61Skre FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \ 871.61Skre sizeof(msg)) == 0) 881.1Skamil 891.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \ 901.61Skre FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \ 911.61Skre sizeof(msg)) == 0) 921.1Skamil 931.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \ 941.61Skre SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \ 951.61Skre sizeof(msg)) == 0) 961.13Schristos 971.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \ 981.13Schristos strerror(errno)) 991.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \ 1001.18Schristos "%d(%s) != %d", res, strerror(res), exp) 1011.13Schristos 1021.13Schristosstatic int debug = 0; 1031.13Schristos 1041.13Schristos#define DPRINTF(a, ...) do \ 1051.123Skamil if (debug) \ 1061.123Skamil printf("%s() %s:%d " a, __func__, __FILE__, __LINE__, ##__VA_ARGS__); \ 1071.13Schristos while (/*CONSTCOND*/0) 1081.1Skamil 1091.110Skamil#ifndef TEST_VFORK_ENABLED 1101.127Skamil#define TEST_VFORK_ENABLED 1 1111.110Skamil#endif 1121.109Skamil 1131.128Skamil#ifndef TEST_LWP_ENABLED 1141.128Skamil#define TEST_LWP_ENABLED 0 1151.128Skamil#endif 1161.128Skamil 1171.34Skamil/// ---------------------------------------------------------------------------- 1181.34Skamil 1191.33Skamilstatic void 1201.33Skamiltraceme_raise(int sigval) 1211.1Skamil{ 1221.1Skamil const int exitval = 5; 1231.1Skamil pid_t child, wpid; 1241.1Skamil#if defined(TWAIT_HAVE_STATUS) 1251.1Skamil int status; 1261.1Skamil#endif 1271.1Skamil 1281.45Skamil struct ptrace_siginfo info; 1291.45Skamil memset(&info, 0, sizeof(info)); 1301.45Skamil 1311.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 1321.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 1331.1Skamil if (child == 0) { 1341.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1351.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1361.1Skamil 1371.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1381.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 1391.1Skamil 1401.36Skamil switch (sigval) { 1411.36Skamil case SIGKILL: 1421.36Skamil /* NOTREACHED */ 1431.36Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 1441.70Smrg __unreachable(); 1451.36Skamil default: 1461.36Skamil DPRINTF("Before exiting of the child process\n"); 1471.36Skamil _exit(exitval); 1481.36Skamil } 1491.1Skamil } 1501.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1511.1Skamil 1521.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1531.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1541.1Skamil 1551.36Skamil switch (sigval) { 1561.36Skamil case SIGKILL: 1571.36Skamil validate_status_signaled(status, sigval, 0); 1581.36Skamil break; 1591.36Skamil default: 1601.36Skamil validate_status_stopped(status, sigval); 1611.1Skamil 1621.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 1631.61Skre "child\n"); 1641.45Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 1651.61Skre sizeof(info)) != -1); 1661.45Skamil 1671.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1681.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 1691.61Skre "si_errno=%#x\n", 1701.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1711.61Skre info.psi_siginfo.si_errno); 1721.45Skamil 1731.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 1741.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 1751.45Skamil 1761.36Skamil DPRINTF("Before resuming the child process where it left off " 1771.36Skamil "and without signal to be sent\n"); 1781.36Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1791.1Skamil 1801.36Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1811.36Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 1821.61Skre child); 1831.36Skamil break; 1841.36Skamil } 1851.1Skamil 1861.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1871.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 1881.1Skamil} 1891.1Skamil 1901.61Skre#define TRACEME_RAISE(test, sig) \ 1911.61SkreATF_TC(test); \ 1921.61SkreATF_TC_HEAD(test, tc) \ 1931.61Skre{ \ 1941.61Skre atf_tc_set_md_var(tc, "descr", \ 1951.61Skre "Verify " #sig " followed by _exit(2) in a child"); \ 1961.61Skre} \ 1971.61Skre \ 1981.61SkreATF_TC_BODY(test, tc) \ 1991.61Skre{ \ 2001.61Skre \ 2011.61Skre traceme_raise(sig); \ 2021.33Skamil} 2031.33Skamil 2041.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */ 2051.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */ 2061.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */ 2071.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP) /* hangup */ 2081.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */ 2091.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */ 2101.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */ 2111.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */ 2121.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */ 2131.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */ 2141.33Skamil 2151.34Skamil/// ---------------------------------------------------------------------------- 2161.1Skamil 2171.1Skamilstatic void 2181.87Skamiltraceme_raisesignal_ignored(int sigignored) 2191.87Skamil{ 2201.87Skamil const int exitval = 5; 2211.87Skamil const int sigval = SIGSTOP; 2221.87Skamil pid_t child, wpid; 2231.87Skamil struct sigaction sa; 2241.87Skamil#if defined(TWAIT_HAVE_STATUS) 2251.87Skamil int status; 2261.87Skamil#endif 2271.87Skamil struct ptrace_siginfo info; 2281.87Skamil 2291.87Skamil memset(&info, 0, sizeof(info)); 2301.87Skamil 2311.87Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 2321.87Skamil SYSCALL_REQUIRE((child = fork()) != -1); 2331.87Skamil if (child == 0) { 2341.87Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2351.87Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2361.87Skamil 2371.87Skamil memset(&sa, 0, sizeof(sa)); 2381.87Skamil sa.sa_handler = SIG_IGN; 2391.87Skamil sigemptyset(&sa.sa_mask); 2401.87Skamil FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1); 2411.87Skamil 2421.87Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 2431.87Skamil FORKEE_ASSERT(raise(sigval) == 0); 2441.87Skamil 2451.87Skamil DPRINTF("Before raising %s from child\n", 2461.87Skamil strsignal(sigignored)); 2471.87Skamil FORKEE_ASSERT(raise(sigignored) == 0); 2481.87Skamil 2491.87Skamil DPRINTF("Before exiting of the child process\n"); 2501.87Skamil _exit(exitval); 2511.87Skamil } 2521.87Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2531.87Skamil 2541.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2551.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2561.87Skamil 2571.87Skamil validate_status_stopped(status, sigval); 2581.87Skamil 2591.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2601.87Skamil SYSCALL_REQUIRE( 2611.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2621.87Skamil 2631.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2641.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2651.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2661.87Skamil info.psi_siginfo.si_errno); 2671.87Skamil 2681.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 2691.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2701.87Skamil 2711.87Skamil DPRINTF("Before resuming the child process where it left off and " 2721.87Skamil "without signal to be sent\n"); 2731.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2741.87Skamil 2751.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2761.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2771.87Skamil 2781.87Skamil validate_status_stopped(status, sigignored); 2791.87Skamil 2801.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2811.87Skamil SYSCALL_REQUIRE( 2821.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2831.87Skamil 2841.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2851.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2861.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2871.87Skamil info.psi_siginfo.si_errno); 2881.87Skamil 2891.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored); 2901.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2911.87Skamil 2921.87Skamil DPRINTF("Before resuming the child process where it left off and " 2931.87Skamil "without signal to be sent\n"); 2941.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2951.87Skamil 2961.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2971.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2981.87Skamil 2991.87Skamil validate_status_exited(status, exitval); 3001.87Skamil 3011.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3021.87Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 3031.87Skamil} 3041.87Skamil 3051.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig) \ 3061.87SkamilATF_TC(test); \ 3071.87SkamilATF_TC_HEAD(test, tc) \ 3081.87Skamil{ \ 3091.87Skamil atf_tc_set_md_var(tc, "descr", \ 3101.87Skamil "Verify that ignoring (with SIG_IGN) " #sig " in tracee " \ 3111.87Skamil "does not stop tracer from catching this raised signal"); \ 3121.87Skamil} \ 3131.87Skamil \ 3141.87SkamilATF_TC_BODY(test, tc) \ 3151.87Skamil{ \ 3161.87Skamil \ 3171.87Skamil traceme_raisesignal_ignored(sig); \ 3181.87Skamil} 3191.87Skamil 3201.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 3211.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */ 3221.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP) /* hangup */ 3231.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */ 3241.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */ 3251.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */ 3261.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */ 3271.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */ 3281.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */ 3291.87Skamil 3301.87Skamil/// ---------------------------------------------------------------------------- 3311.87Skamil 3321.87Skamilstatic void 3331.86Skamiltraceme_raisesignal_masked(int sigmasked) 3341.86Skamil{ 3351.86Skamil const int exitval = 5; 3361.86Skamil const int sigval = SIGSTOP; 3371.86Skamil pid_t child, wpid; 3381.86Skamil#if defined(TWAIT_HAVE_STATUS) 3391.86Skamil int status; 3401.86Skamil#endif 3411.86Skamil sigset_t intmask; 3421.86Skamil struct ptrace_siginfo info; 3431.86Skamil 3441.86Skamil memset(&info, 0, sizeof(info)); 3451.86Skamil 3461.86Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 3471.86Skamil SYSCALL_REQUIRE((child = fork()) != -1); 3481.86Skamil if (child == 0) { 3491.86Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 3501.86Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 3511.86Skamil 3521.86Skamil sigemptyset(&intmask); 3531.86Skamil sigaddset(&intmask, sigmasked); 3541.86Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 3551.86Skamil 3561.86Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 3571.86Skamil FORKEE_ASSERT(raise(sigval) == 0); 3581.86Skamil 3591.86Skamil DPRINTF("Before raising %s breakpoint from child\n", 3601.86Skamil strsignal(sigmasked)); 3611.86Skamil FORKEE_ASSERT(raise(sigmasked) == 0); 3621.86Skamil 3631.86Skamil DPRINTF("Before exiting of the child process\n"); 3641.86Skamil _exit(exitval); 3651.86Skamil } 3661.86Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 3671.86Skamil 3681.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3691.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3701.86Skamil 3711.86Skamil validate_status_stopped(status, sigval); 3721.86Skamil 3731.86Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 3741.86Skamil SYSCALL_REQUIRE( 3751.86Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 3761.86Skamil 3771.86Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 3781.86Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 3791.86Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 3801.86Skamil info.psi_siginfo.si_errno); 3811.86Skamil 3821.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 3831.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 3841.86Skamil 3851.86Skamil DPRINTF("Before resuming the child process where it left off and " 3861.86Skamil "without signal to be sent\n"); 3871.86Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 3881.86Skamil 3891.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3901.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3911.86Skamil 3921.86Skamil validate_status_exited(status, exitval); 3931.86Skamil 3941.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3951.86Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 3961.86Skamil} 3971.86Skamil 3981.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig) \ 3991.86SkamilATF_TC(test); \ 4001.86SkamilATF_TC_HEAD(test, tc) \ 4011.86Skamil{ \ 4021.86Skamil atf_tc_set_md_var(tc, "descr", \ 4031.86Skamil "Verify that masking (with SIG_BLOCK) " #sig " in tracee " \ 4041.86Skamil "stops tracer from catching this raised signal"); \ 4051.86Skamil} \ 4061.86Skamil \ 4071.86SkamilATF_TC_BODY(test, tc) \ 4081.86Skamil{ \ 4091.86Skamil \ 4101.86Skamil traceme_raisesignal_masked(sig); \ 4111.86Skamil} 4121.86Skamil 4131.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 4141.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */ 4151.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP) /* hangup */ 4161.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */ 4171.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */ 4181.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */ 4191.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */ 4201.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */ 4211.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */ 4221.86Skamil 4231.86Skamil/// ---------------------------------------------------------------------------- 4241.86Skamil 4251.86Skamilstatic void 4261.59Skamiltraceme_crash(int sig) 4271.59Skamil{ 4281.59Skamil pid_t child, wpid; 4291.59Skamil#if defined(TWAIT_HAVE_STATUS) 4301.59Skamil int status; 4311.59Skamil#endif 4321.59Skamil struct ptrace_siginfo info; 4331.61Skre 4341.71Skamil#ifndef PTRACE_ILLEGAL_ASM 4351.71Skamil if (sig == SIGILL) 4361.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 4371.71Skamil#endif 4381.71Skamil 4391.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 4401.114Skamil atf_tc_skip("FP exceptions are not supported"); 4411.114Skamil 4421.59Skamil memset(&info, 0, sizeof(info)); 4431.59Skamil 4441.59Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 4451.59Skamil SYSCALL_REQUIRE((child = fork()) != -1); 4461.59Skamil if (child == 0) { 4471.59Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 4481.59Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 4491.59Skamil 4501.59Skamil DPRINTF("Before executing a trap\n"); 4511.59Skamil switch (sig) { 4521.59Skamil case SIGTRAP: 4531.59Skamil trigger_trap(); 4541.59Skamil break; 4551.59Skamil case SIGSEGV: 4561.59Skamil trigger_segv(); 4571.59Skamil break; 4581.59Skamil case SIGILL: 4591.59Skamil trigger_ill(); 4601.59Skamil break; 4611.59Skamil case SIGFPE: 4621.59Skamil trigger_fpe(); 4631.59Skamil break; 4641.59Skamil case SIGBUS: 4651.59Skamil trigger_bus(); 4661.59Skamil break; 4671.59Skamil default: 4681.59Skamil /* NOTREACHED */ 4691.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4701.59Skamil } 4711.59Skamil 4721.59Skamil /* NOTREACHED */ 4731.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4741.59Skamil } 4751.59Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 4761.59Skamil 4771.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4781.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4791.59Skamil 4801.59Skamil validate_status_stopped(status, sig); 4811.59Skamil 4821.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 4831.61Skre SYSCALL_REQUIRE( 4841.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 4851.59Skamil 4861.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 4871.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 4881.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 4891.61Skre info.psi_siginfo.si_errno); 4901.59Skamil 4911.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 4921.59Skamil switch (sig) { 4931.59Skamil case SIGTRAP: 4941.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 4951.59Skamil break; 4961.59Skamil case SIGSEGV: 4971.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 4981.59Skamil break; 4991.71Skamil case SIGILL: 5001.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 5011.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 5021.71Skamil break; 5031.59Skamil case SIGFPE: 5041.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 5051.59Skamil break; 5061.59Skamil case SIGBUS: 5071.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 5081.59Skamil break; 5091.59Skamil } 5101.59Skamil 5111.59Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 5121.59Skamil 5131.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5141.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 5151.59Skamil 5161.59Skamil validate_status_signaled(status, SIGKILL, 0); 5171.59Skamil 5181.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5191.59Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 5201.59Skamil} 5211.59Skamil 5221.61Skre#define TRACEME_CRASH(test, sig) \ 5231.61SkreATF_TC(test); \ 5241.61SkreATF_TC_HEAD(test, tc) \ 5251.61Skre{ \ 5261.61Skre atf_tc_set_md_var(tc, "descr", \ 5271.61Skre "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \ 5281.61Skre} \ 5291.61Skre \ 5301.61SkreATF_TC_BODY(test, tc) \ 5311.61Skre{ \ 5321.61Skre \ 5331.61Skre traceme_crash(sig); \ 5341.59Skamil} 5351.59Skamil 5361.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP) 5371.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV) 5381.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL) 5391.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE) 5401.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS) 5411.59Skamil 5421.59Skamil/// ---------------------------------------------------------------------------- 5431.59Skamil 5441.59Skamilstatic void 5451.88Skamiltraceme_signalmasked_crash(int sig) 5461.88Skamil{ 5471.89Skamil const int sigval = SIGSTOP; 5481.88Skamil pid_t child, wpid; 5491.88Skamil#if defined(TWAIT_HAVE_STATUS) 5501.88Skamil int status; 5511.88Skamil#endif 5521.88Skamil struct ptrace_siginfo info; 5531.88Skamil sigset_t intmask; 5541.89Skamil struct kinfo_proc2 kp; 5551.89Skamil size_t len = sizeof(kp); 5561.89Skamil 5571.89Skamil int name[6]; 5581.89Skamil const size_t namelen = __arraycount(name); 5591.89Skamil ki_sigset_t kp_sigmask; 5601.88Skamil 5611.88Skamil#ifndef PTRACE_ILLEGAL_ASM 5621.88Skamil if (sig == SIGILL) 5631.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 5641.88Skamil#endif 5651.88Skamil 5661.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 5671.114Skamil atf_tc_skip("FP exceptions are not supported"); 5681.114Skamil 5691.88Skamil memset(&info, 0, sizeof(info)); 5701.88Skamil 5711.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 5721.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 5731.88Skamil if (child == 0) { 5741.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 5751.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 5761.88Skamil 5771.88Skamil sigemptyset(&intmask); 5781.88Skamil sigaddset(&intmask, sig); 5791.88Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 5801.88Skamil 5811.89Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 5821.89Skamil FORKEE_ASSERT(raise(sigval) == 0); 5831.89Skamil 5841.88Skamil DPRINTF("Before executing a trap\n"); 5851.88Skamil switch (sig) { 5861.88Skamil case SIGTRAP: 5871.88Skamil trigger_trap(); 5881.88Skamil break; 5891.88Skamil case SIGSEGV: 5901.88Skamil trigger_segv(); 5911.88Skamil break; 5921.88Skamil case SIGILL: 5931.88Skamil trigger_ill(); 5941.88Skamil break; 5951.88Skamil case SIGFPE: 5961.88Skamil trigger_fpe(); 5971.88Skamil break; 5981.88Skamil case SIGBUS: 5991.88Skamil trigger_bus(); 6001.88Skamil break; 6011.88Skamil default: 6021.88Skamil /* NOTREACHED */ 6031.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 6041.88Skamil } 6051.88Skamil 6061.88Skamil /* NOTREACHED */ 6071.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 6081.88Skamil } 6091.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 6101.88Skamil 6111.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6121.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6131.88Skamil 6141.89Skamil validate_status_stopped(status, sigval); 6151.89Skamil 6161.89Skamil name[0] = CTL_KERN, 6171.89Skamil name[1] = KERN_PROC2, 6181.89Skamil name[2] = KERN_PROC_PID; 6191.89Skamil name[3] = child; 6201.89Skamil name[4] = sizeof(kp); 6211.89Skamil name[5] = 1; 6221.89Skamil 6231.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6241.89Skamil 6251.89Skamil kp_sigmask = kp.p_sigmask; 6261.89Skamil 6271.89Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 6281.89Skamil SYSCALL_REQUIRE( 6291.89Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6301.89Skamil 6311.89Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6321.89Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6331.89Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6341.89Skamil info.psi_siginfo.si_errno); 6351.89Skamil 6361.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 6371.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 6381.89Skamil 6391.89Skamil DPRINTF("Before resuming the child process where it left off and " 6401.89Skamil "without signal to be sent\n"); 6411.89Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 6421.89Skamil 6431.89Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6441.89Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6451.89Skamil 6461.88Skamil validate_status_stopped(status, sig); 6471.88Skamil 6481.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 6491.88Skamil SYSCALL_REQUIRE( 6501.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6511.88Skamil 6521.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6531.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6541.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6551.88Skamil info.psi_siginfo.si_errno); 6561.88Skamil 6571.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6581.89Skamil 6591.89Skamil DPRINTF("kp_sigmask=" 6601.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6611.89Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2], 6621.89Skamil kp_sigmask.__bits[3]); 6631.89Skamil 6641.89Skamil DPRINTF("kp.p_sigmask=" 6651.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6661.89Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 6671.89Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 6681.89Skamil 6691.89Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask))); 6701.89Skamil 6711.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 6721.88Skamil switch (sig) { 6731.88Skamil case SIGTRAP: 6741.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 6751.88Skamil break; 6761.88Skamil case SIGSEGV: 6771.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 6781.88Skamil break; 6791.88Skamil case SIGILL: 6801.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 6811.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 6821.88Skamil break; 6831.88Skamil case SIGFPE: 6841.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 6851.88Skamil break; 6861.88Skamil case SIGBUS: 6871.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 6881.88Skamil break; 6891.88Skamil } 6901.88Skamil 6911.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 6921.88Skamil 6931.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6941.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6951.88Skamil 6961.88Skamil validate_status_signaled(status, SIGKILL, 0); 6971.88Skamil 6981.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6991.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 7001.88Skamil} 7011.88Skamil 7021.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig) \ 7031.88SkamilATF_TC(test); \ 7041.88SkamilATF_TC_HEAD(test, tc) \ 7051.88Skamil{ \ 7061.88Skamil atf_tc_set_md_var(tc, "descr", \ 7071.88Skamil "Verify masked crash signal " #sig " in a child after " \ 7081.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 7091.88Skamil} \ 7101.88Skamil \ 7111.88SkamilATF_TC_BODY(test, tc) \ 7121.88Skamil{ \ 7131.88Skamil \ 7141.88Skamil traceme_signalmasked_crash(sig); \ 7151.88Skamil} 7161.88Skamil 7171.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP) 7181.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV) 7191.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL) 7201.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE) 7211.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS) 7221.88Skamil 7231.88Skamil/// ---------------------------------------------------------------------------- 7241.88Skamil 7251.88Skamilstatic void 7261.88Skamiltraceme_signalignored_crash(int sig) 7271.88Skamil{ 7281.90Skamil const int sigval = SIGSTOP; 7291.88Skamil pid_t child, wpid; 7301.88Skamil#if defined(TWAIT_HAVE_STATUS) 7311.88Skamil int status; 7321.88Skamil#endif 7331.88Skamil struct sigaction sa; 7341.88Skamil struct ptrace_siginfo info; 7351.90Skamil struct kinfo_proc2 kp; 7361.90Skamil size_t len = sizeof(kp); 7371.90Skamil 7381.90Skamil int name[6]; 7391.90Skamil const size_t namelen = __arraycount(name); 7401.90Skamil ki_sigset_t kp_sigignore; 7411.88Skamil 7421.88Skamil#ifndef PTRACE_ILLEGAL_ASM 7431.88Skamil if (sig == SIGILL) 7441.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 7451.88Skamil#endif 7461.88Skamil 7471.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 7481.114Skamil atf_tc_skip("FP exceptions are not supported"); 7491.114Skamil 7501.88Skamil memset(&info, 0, sizeof(info)); 7511.88Skamil 7521.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 7531.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 7541.88Skamil if (child == 0) { 7551.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 7561.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 7571.88Skamil 7581.88Skamil memset(&sa, 0, sizeof(sa)); 7591.88Skamil sa.sa_handler = SIG_IGN; 7601.88Skamil sigemptyset(&sa.sa_mask); 7611.88Skamil 7621.88Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 7631.88Skamil 7641.90Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 7651.90Skamil FORKEE_ASSERT(raise(sigval) == 0); 7661.90Skamil 7671.88Skamil DPRINTF("Before executing a trap\n"); 7681.88Skamil switch (sig) { 7691.88Skamil case SIGTRAP: 7701.88Skamil trigger_trap(); 7711.88Skamil break; 7721.88Skamil case SIGSEGV: 7731.88Skamil trigger_segv(); 7741.88Skamil break; 7751.88Skamil case SIGILL: 7761.88Skamil trigger_ill(); 7771.88Skamil break; 7781.88Skamil case SIGFPE: 7791.88Skamil trigger_fpe(); 7801.88Skamil break; 7811.88Skamil case SIGBUS: 7821.88Skamil trigger_bus(); 7831.88Skamil break; 7841.88Skamil default: 7851.88Skamil /* NOTREACHED */ 7861.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7871.88Skamil } 7881.88Skamil 7891.88Skamil /* NOTREACHED */ 7901.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7911.88Skamil } 7921.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 7931.88Skamil 7941.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7951.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 7961.88Skamil 7971.90Skamil validate_status_stopped(status, sigval); 7981.90Skamil 7991.90Skamil name[0] = CTL_KERN, 8001.90Skamil name[1] = KERN_PROC2, 8011.90Skamil name[2] = KERN_PROC_PID; 8021.90Skamil name[3] = child; 8031.90Skamil name[4] = sizeof(kp); 8041.90Skamil name[5] = 1; 8051.90Skamil 8061.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8071.90Skamil 8081.90Skamil kp_sigignore = kp.p_sigignore; 8091.90Skamil 8101.90Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 8111.90Skamil SYSCALL_REQUIRE( 8121.90Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8131.90Skamil 8141.90Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8151.90Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8161.90Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8171.90Skamil info.psi_siginfo.si_errno); 8181.90Skamil 8191.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 8201.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 8211.90Skamil 8221.90Skamil DPRINTF("Before resuming the child process where it left off and " 8231.90Skamil "without signal to be sent\n"); 8241.90Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 8251.90Skamil 8261.90Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8271.90Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8281.90Skamil 8291.88Skamil validate_status_stopped(status, sig); 8301.88Skamil 8311.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 8321.88Skamil SYSCALL_REQUIRE( 8331.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8341.88Skamil 8351.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8361.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8371.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8381.88Skamil info.psi_siginfo.si_errno); 8391.88Skamil 8401.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8411.90Skamil 8421.90Skamil DPRINTF("kp_sigignore=" 8431.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8441.90Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 8451.90Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 8461.90Skamil 8471.90Skamil DPRINTF("kp.p_sigignore=" 8481.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8491.90Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 8501.90Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 8511.90Skamil 8521.90Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore))); 8531.90Skamil 8541.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 8551.88Skamil switch (sig) { 8561.88Skamil case SIGTRAP: 8571.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 8581.88Skamil break; 8591.88Skamil case SIGSEGV: 8601.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 8611.88Skamil break; 8621.88Skamil case SIGILL: 8631.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 8641.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 8651.88Skamil break; 8661.88Skamil case SIGFPE: 8671.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 8681.88Skamil break; 8691.88Skamil case SIGBUS: 8701.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 8711.88Skamil break; 8721.88Skamil } 8731.88Skamil 8741.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 8751.88Skamil 8761.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8771.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8781.88Skamil 8791.88Skamil validate_status_signaled(status, SIGKILL, 0); 8801.88Skamil 8811.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8821.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 8831.88Skamil} 8841.88Skamil 8851.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig) \ 8861.88SkamilATF_TC(test); \ 8871.88SkamilATF_TC_HEAD(test, tc) \ 8881.88Skamil{ \ 8891.88Skamil atf_tc_set_md_var(tc, "descr", \ 8901.88Skamil "Verify ignored crash signal " #sig " in a child after " \ 8911.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 8921.88Skamil} \ 8931.88Skamil \ 8941.88SkamilATF_TC_BODY(test, tc) \ 8951.88Skamil{ \ 8961.88Skamil \ 8971.88Skamil traceme_signalignored_crash(sig); \ 8981.88Skamil} 8991.88Skamil 9001.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP) 9011.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV) 9021.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL) 9031.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE) 9041.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS) 9051.88Skamil 9061.88Skamil/// ---------------------------------------------------------------------------- 9071.88Skamil 9081.88Skamilstatic void 9091.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught) 9101.1Skamil{ 9111.1Skamil const int exitval = 5; 9121.34Skamil const int sigval = SIGSTOP; 9131.1Skamil pid_t child, wpid; 9141.1Skamil struct sigaction sa; 9151.1Skamil#if defined(TWAIT_HAVE_STATUS) 9161.1Skamil int status; 9171.1Skamil#endif 9181.61Skre struct ptrace_siginfo info; 9191.1Skamil 9201.45Skamil memset(&info, 0, sizeof(info)); 9211.45Skamil 9221.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 9231.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 9241.1Skamil if (child == 0) { 9251.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 9261.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 9271.1Skamil 9281.34Skamil sa.sa_handler = sah; 9291.1Skamil sa.sa_flags = SA_SIGINFO; 9301.1Skamil sigemptyset(&sa.sa_mask); 9311.1Skamil 9321.1Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 9331.1Skamil 9341.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 9351.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 9361.1Skamil 9371.34Skamil FORKEE_ASSERT_EQ(*traceme_caught, 1); 9381.1Skamil 9391.13Schristos DPRINTF("Before exiting of the child process\n"); 9401.1Skamil _exit(exitval); 9411.1Skamil } 9421.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 9431.1Skamil 9441.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9451.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9461.1Skamil 9471.1Skamil validate_status_stopped(status, sigval); 9481.1Skamil 9491.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 9501.61Skre SYSCALL_REQUIRE( 9511.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 9521.45Skamil 9531.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 9541.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 9551.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 9561.45Skamil info.psi_siginfo.si_errno); 9571.45Skamil 9581.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 9591.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 9601.45Skamil 9611.13Schristos DPRINTF("Before resuming the child process where it left off and with " 9621.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 9631.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 9641.1Skamil 9651.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9661.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9671.1Skamil 9681.1Skamil validate_status_exited(status, exitval); 9691.1Skamil 9701.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 9711.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 9721.1Skamil} 9731.1Skamil 9741.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig) \ 9751.61SkreATF_TC(test); \ 9761.61SkreATF_TC_HEAD(test, tc) \ 9771.61Skre{ \ 9781.61Skre atf_tc_set_md_var(tc, "descr", \ 9791.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 9801.61Skre "handled correctly and caught by a signal handler"); \ 9811.61Skre} \ 9821.61Skre \ 9831.61Skrestatic int test##_caught = 0; \ 9841.61Skre \ 9851.61Skrestatic void \ 9861.61Skretest##_sighandler(int arg) \ 9871.61Skre{ \ 9881.61Skre FORKEE_ASSERT_EQ(arg, sig); \ 9891.61Skre \ 9901.61Skre ++ test##_caught; \ 9911.61Skre} \ 9921.61Skre \ 9931.61SkreATF_TC_BODY(test, tc) \ 9941.61Skre{ \ 9951.61Skre \ 9961.61Skre traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \ 9971.34Skamil} 9981.34Skamil 9991.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered. 10001.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */ 10011.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP) /* hangup */ 10021.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */ 10031.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */ 10041.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */ 10051.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */ 10061.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */ 10071.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */ 10081.34Skamil 10091.34Skamil/// ---------------------------------------------------------------------------- 10101.34Skamil 10111.35Skamilstatic void 10121.50Skamiltraceme_sendsignal_masked(int sigsent) 10131.50Skamil{ 10141.50Skamil const int exitval = 5; 10151.50Skamil const int sigval = SIGSTOP; 10161.50Skamil pid_t child, wpid; 10171.50Skamil sigset_t set; 10181.50Skamil#if defined(TWAIT_HAVE_STATUS) 10191.50Skamil int status; 10201.50Skamil#endif 10211.61Skre struct ptrace_siginfo info; 10221.50Skamil 10231.50Skamil memset(&info, 0, sizeof(info)); 10241.50Skamil 10251.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 10261.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 10271.50Skamil if (child == 0) { 10281.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 10291.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 10301.50Skamil 10311.50Skamil sigemptyset(&set); 10321.50Skamil sigaddset(&set, sigsent); 10331.50Skamil FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 10341.50Skamil 10351.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 10361.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 10371.50Skamil 10381.50Skamil _exit(exitval); 10391.50Skamil } 10401.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 10411.50Skamil 10421.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10431.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10441.50Skamil 10451.50Skamil validate_status_stopped(status, sigval); 10461.50Skamil 10471.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 10481.61Skre SYSCALL_REQUIRE( 10491.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 10501.50Skamil 10511.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 10521.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 10531.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 10541.50Skamil info.psi_siginfo.si_errno); 10551.50Skamil 10561.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 10571.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 10581.50Skamil 10591.50Skamil DPRINTF("Before resuming the child process where it left off and with " 10601.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 10611.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 10621.50Skamil 10631.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10641.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10651.50Skamil 10661.50Skamil validate_status_exited(status, exitval); 10671.50Skamil 10681.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 10691.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 10701.50Skamil} 10711.50Skamil 10721.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig) \ 10731.61SkreATF_TC(test); \ 10741.61SkreATF_TC_HEAD(test, tc) \ 10751.61Skre{ \ 10761.61Skre atf_tc_set_md_var(tc, "descr", \ 10771.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 10781.61Skre "handled correctly and the signal is masked by SIG_BLOCK"); \ 10791.61Skre} \ 10801.61Skre \ 10811.61SkreATF_TC_BODY(test, tc) \ 10821.61Skre{ \ 10831.61Skre \ 10841.61Skre traceme_sendsignal_masked(sig); \ 10851.50Skamil} 10861.50Skamil 10871.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 10881.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */ 10891.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP) /* hangup */ 10901.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */ 10911.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */ 10921.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */ 10931.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */ 10941.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */ 10951.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */ 10961.50Skamil 10971.50Skamil/// ---------------------------------------------------------------------------- 10981.50Skamil 10991.50Skamilstatic void 11001.50Skamiltraceme_sendsignal_ignored(int sigsent) 11011.50Skamil{ 11021.50Skamil const int exitval = 5; 11031.50Skamil const int sigval = SIGSTOP; 11041.50Skamil pid_t child, wpid; 11051.50Skamil struct sigaction sa; 11061.50Skamil#if defined(TWAIT_HAVE_STATUS) 11071.50Skamil int status; 11081.50Skamil#endif 11091.61Skre struct ptrace_siginfo info; 11101.50Skamil 11111.50Skamil memset(&info, 0, sizeof(info)); 11121.50Skamil 11131.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 11141.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 11151.50Skamil if (child == 0) { 11161.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 11171.61Skre 11181.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 11191.50Skamil 11201.50Skamil memset(&sa, 0, sizeof(sa)); 11211.50Skamil sa.sa_handler = SIG_IGN; 11221.50Skamil sigemptyset(&sa.sa_mask); 11231.50Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 11241.50Skamil 11251.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 11261.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 11271.50Skamil 11281.50Skamil _exit(exitval); 11291.50Skamil } 11301.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 11311.50Skamil 11321.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11331.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11341.50Skamil 11351.50Skamil validate_status_stopped(status, sigval); 11361.50Skamil 11371.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 11381.61Skre SYSCALL_REQUIRE( 11391.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 11401.50Skamil 11411.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 11421.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 11431.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 11441.50Skamil info.psi_siginfo.si_errno); 11451.50Skamil 11461.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 11471.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 11481.50Skamil 11491.50Skamil DPRINTF("Before resuming the child process where it left off and with " 11501.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 11511.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 11521.50Skamil 11531.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11541.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11551.50Skamil 11561.50Skamil validate_status_exited(status, exitval); 11571.50Skamil 11581.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 11591.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 11601.50Skamil} 11611.50Skamil 11621.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig) \ 11631.61SkreATF_TC(test); \ 11641.61SkreATF_TC_HEAD(test, tc) \ 11651.61Skre{ \ 11661.61Skre atf_tc_set_md_var(tc, "descr", \ 11671.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 11681.61Skre "handled correctly and the signal is masked by SIG_IGN"); \ 11691.61Skre} \ 11701.61Skre \ 11711.61SkreATF_TC_BODY(test, tc) \ 11721.61Skre{ \ 11731.61Skre \ 11741.61Skre traceme_sendsignal_ignored(sig); \ 11751.50Skamil} 11761.50Skamil 11771.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 11781.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */ 11791.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP) /* hangup */ 11801.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */ 11811.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */ 11821.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */ 11831.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */ 11841.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */ 11851.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */ 11861.50Skamil 11871.50Skamil/// ---------------------------------------------------------------------------- 11881.50Skamil 11891.50Skamilstatic void 11901.50Skamiltraceme_sendsignal_simple(int sigsent) 11911.1Skamil{ 11921.35Skamil const int sigval = SIGSTOP; 11931.35Skamil int exitval = 0; 11941.1Skamil pid_t child, wpid; 11951.1Skamil#if defined(TWAIT_HAVE_STATUS) 11961.1Skamil int status; 11971.85Skamil int expect_core; 11981.85Skamil 11991.85Skamil switch (sigsent) { 12001.85Skamil case SIGABRT: 12011.85Skamil case SIGTRAP: 12021.85Skamil case SIGBUS: 12031.85Skamil case SIGILL: 12041.85Skamil case SIGFPE: 12051.85Skamil case SIGSEGV: 12061.85Skamil expect_core = 1; 12071.85Skamil break; 12081.85Skamil default: 12091.85Skamil expect_core = 0; 12101.85Skamil break; 12111.85Skamil } 12121.1Skamil#endif 12131.61Skre struct ptrace_siginfo info; 12141.1Skamil 12151.45Skamil memset(&info, 0, sizeof(info)); 12161.45Skamil 12171.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 12181.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 12191.1Skamil if (child == 0) { 12201.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 12211.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 12221.1Skamil 12231.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 12241.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 12251.1Skamil 12261.35Skamil switch (sigsent) { 12271.35Skamil case SIGCONT: 12281.48Skamil case SIGSTOP: 12291.35Skamil _exit(exitval); 12301.35Skamil default: 12311.35Skamil /* NOTREACHED */ 12321.35Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 12331.35Skamil } 12341.1Skamil } 12351.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 12361.1Skamil 12371.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12381.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12391.1Skamil 12401.1Skamil validate_status_stopped(status, sigval); 12411.1Skamil 12421.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 12431.61Skre SYSCALL_REQUIRE( 12441.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 12451.45Skamil 12461.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12471.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 12481.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12491.45Skamil info.psi_siginfo.si_errno); 12501.45Skamil 12511.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12521.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12531.45Skamil 12541.13Schristos DPRINTF("Before resuming the child process where it left off and with " 12551.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 12561.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 12571.1Skamil 12581.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12591.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12601.1Skamil 12611.35Skamil switch (sigsent) { 12621.48Skamil case SIGSTOP: 12631.48Skamil validate_status_stopped(status, sigsent); 12641.48Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 12651.61Skre "child\n"); 12661.48Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 12671.61Skre sizeof(info)) != -1); 12681.48Skamil 12691.48Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12701.48Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 12711.61Skre "si_errno=%#x\n", 12721.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12731.61Skre info.psi_siginfo.si_errno); 12741.48Skamil 12751.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12761.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12771.48Skamil 12781.48Skamil DPRINTF("Before resuming the child process where it left off " 12791.61Skre "and with signal %s to be sent\n", strsignal(sigsent)); 12801.48Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 12811.48Skamil 12821.48Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12831.48Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 12841.61Skre child); 12851.48Skamil /* FALLTHROUGH */ 12861.35Skamil case SIGCONT: 12871.35Skamil validate_status_exited(status, exitval); 12881.35Skamil break; 12891.35Skamil default: 12901.35Skamil validate_status_signaled(status, sigsent, expect_core); 12911.35Skamil break; 12921.35Skamil } 12931.1Skamil 12941.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 12951.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 12961.1Skamil} 12971.1Skamil 12981.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig) \ 12991.61SkreATF_TC(test); \ 13001.61SkreATF_TC_HEAD(test, tc) \ 13011.61Skre{ \ 13021.61Skre atf_tc_set_md_var(tc, "descr", \ 13031.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 13041.61Skre "handled correctly in a child without a signal handler"); \ 13051.61Skre} \ 13061.61Skre \ 13071.61SkreATF_TC_BODY(test, tc) \ 13081.61Skre{ \ 13091.61Skre \ 13101.61Skre traceme_sendsignal_simple(sig); \ 13111.35Skamil} 13121.35Skamil 13131.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/ 13141.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/ 13151.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */ 13161.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP) /* hangup */ 13171.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */ 13181.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */ 13191.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */ 13201.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */ 13211.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */ 13221.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */ 13231.35Skamil 13241.35Skamil/// ---------------------------------------------------------------------------- 13251.35Skamil 13261.37SkamilATF_TC(traceme_pid1_parent); 13271.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc) 13281.37Skamil{ 13291.37Skamil atf_tc_set_md_var(tc, "descr", 13301.37Skamil "Verify that PT_TRACE_ME is not allowed when our parent is PID1"); 13311.37Skamil} 13321.37Skamil 13331.37SkamilATF_TC_BODY(traceme_pid1_parent, tc) 13341.37Skamil{ 13351.37Skamil struct msg_fds parent_child; 13361.37Skamil int exitval_child1 = 1, exitval_child2 = 2; 13371.37Skamil pid_t child1, child2, wpid; 13381.37Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 13391.37Skamil#if defined(TWAIT_HAVE_STATUS) 13401.37Skamil int status; 13411.37Skamil#endif 13421.37Skamil 13431.37Skamil SYSCALL_REQUIRE(msg_open(&parent_child) == 0); 13441.37Skamil 13451.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13461.37Skamil SYSCALL_REQUIRE((child1 = fork()) != -1); 13471.37Skamil if (child1 == 0) { 13481.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13491.37Skamil SYSCALL_REQUIRE((child2 = fork()) != -1); 13501.37Skamil if (child2 != 0) { 13511.37Skamil DPRINTF("Parent process PID=%d, child2's PID=%d\n", 13521.61Skre getpid(), child2); 13531.37Skamil _exit(exitval_child1); 13541.37Skamil } 13551.37Skamil CHILD_FROM_PARENT("exit child1", parent_child, msg); 13561.37Skamil 13571.37Skamil DPRINTF("Assert that our parent is PID1 (initproc)\n"); 13581.37Skamil FORKEE_ASSERT_EQ(getppid(), 1); 13591.37Skamil 13601.37Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 13611.37Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1); 13621.37Skamil SYSCALL_REQUIRE_ERRNO(errno, EPERM); 13631.37Skamil 13641.37Skamil CHILD_TO_PARENT("child2 exiting", parent_child, msg); 13651.37Skamil 13661.37Skamil _exit(exitval_child2); 13671.37Skamil } 13681.37Skamil DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1); 13691.37Skamil 13701.37Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 13711.61Skre TWAIT_REQUIRE_SUCCESS( 13721.61Skre wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1); 13731.37Skamil 13741.37Skamil validate_status_exited(status, exitval_child1); 13751.37Skamil 13761.37Skamil DPRINTF("Notify that child1 is dead\n"); 13771.37Skamil PARENT_TO_CHILD("exit child1", parent_child, msg); 13781.37Skamil 13791.37Skamil DPRINTF("Wait for exiting of child2\n"); 13801.37Skamil PARENT_FROM_CHILD("child2 exiting", parent_child, msg); 13811.37Skamil} 13821.37Skamil 13831.37Skamil/// ---------------------------------------------------------------------------- 13841.37Skamil 13851.40Skamilstatic void 13861.40Skamiltraceme_vfork_raise(int sigval) 13871.40Skamil{ 13881.46Skamil const int exitval = 5, exitval_watcher = 10; 13891.46Skamil pid_t child, parent, watcher, wpid; 13901.46Skamil int rv; 13911.40Skamil#if defined(TWAIT_HAVE_STATUS) 13921.40Skamil int status; 13931.85Skamil 13941.85Skamil /* volatile workarounds GCC -Werror=clobbered */ 13951.85Skamil volatile int expect_core; 13961.85Skamil 13971.85Skamil switch (sigval) { 13981.85Skamil case SIGABRT: 13991.85Skamil case SIGTRAP: 14001.85Skamil case SIGBUS: 14011.85Skamil case SIGILL: 14021.85Skamil case SIGFPE: 14031.85Skamil case SIGSEGV: 14041.85Skamil expect_core = 1; 14051.85Skamil break; 14061.85Skamil default: 14071.85Skamil expect_core = 0; 14081.85Skamil break; 14091.85Skamil } 14101.40Skamil#endif 14111.40Skamil 14121.46Skamil /* 14131.46Skamil * Spawn a dedicated thread to watch for a stopped child and emit 14141.46Skamil * the SIGKILL signal to it. 14151.46Skamil * 14161.46Skamil * vfork(2) might clobber watcher, this means that it's safer and 14171.46Skamil * simpler to reparent this process to initproc and forget about it. 14181.46Skamil */ 14191.46Skamil if (sigval == SIGSTOP) { 14201.46Skamil parent = getpid(); 14211.46Skamil 14221.46Skamil watcher = fork(); 14231.46Skamil ATF_REQUIRE(watcher != 1); 14241.46Skamil if (watcher == 0) { 14251.46Skamil /* Double fork(2) trick to reparent to initproc */ 14261.46Skamil watcher = fork(); 14271.46Skamil FORKEE_ASSERT_NEQ(watcher, -1); 14281.46Skamil if (watcher != 0) 14291.46Skamil _exit(exitval_watcher); 14301.46Skamil 14311.46Skamil child = await_stopped_child(parent); 14321.46Skamil 14331.46Skamil errno = 0; 14341.46Skamil rv = kill(child, SIGKILL); 14351.46Skamil FORKEE_ASSERT_EQ(rv, 0); 14361.46Skamil FORKEE_ASSERT_EQ(errno, 0); 14371.46Skamil 14381.46Skamil /* This exit value will be collected by initproc */ 14391.46Skamil _exit(0); 14401.46Skamil } 14411.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14421.46Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0), 14431.61Skre watcher); 14441.46Skamil 14451.46Skamil validate_status_exited(status, exitval_watcher); 14461.46Skamil 14471.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14481.61Skre TWAIT_REQUIRE_FAILURE(ECHILD, 14491.61Skre wpid = TWAIT_GENERIC(watcher, &status, 0)); 14501.46Skamil } 14511.46Skamil 14521.40Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 14531.40Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 14541.40Skamil if (child == 0) { 14551.40Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 14561.40Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 14571.40Skamil 14581.40Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 14591.40Skamil FORKEE_ASSERT(raise(sigval) == 0); 14601.40Skamil 14611.40Skamil switch (sigval) { 14621.46Skamil case SIGSTOP: 14631.40Skamil case SIGKILL: 14641.40Skamil case SIGABRT: 14651.40Skamil case SIGHUP: 14661.85Skamil case SIGTRAP: 14671.85Skamil case SIGBUS: 14681.85Skamil case SIGILL: 14691.85Skamil case SIGFPE: 14701.85Skamil case SIGSEGV: 14711.40Skamil /* NOTREACHED */ 14721.40Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 14731.70Smrg __unreachable(); 14741.40Skamil default: 14751.40Skamil DPRINTF("Before exiting of the child process\n"); 14761.40Skamil _exit(exitval); 14771.40Skamil } 14781.40Skamil } 14791.40Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 14801.40Skamil 14811.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14821.40Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 14831.40Skamil 14841.40Skamil switch (sigval) { 14851.40Skamil case SIGKILL: 14861.40Skamil case SIGABRT: 14871.40Skamil case SIGHUP: 14881.85Skamil case SIGTRAP: 14891.85Skamil case SIGBUS: 14901.85Skamil case SIGILL: 14911.85Skamil case SIGFPE: 14921.85Skamil case SIGSEGV: 14931.40Skamil validate_status_signaled(status, sigval, expect_core); 14941.40Skamil break; 14951.40Skamil case SIGSTOP: 14961.46Skamil validate_status_signaled(status, SIGKILL, 0); 14971.46Skamil break; 14981.40Skamil case SIGCONT: 14991.47Skamil case SIGTSTP: 15001.47Skamil case SIGTTIN: 15011.47Skamil case SIGTTOU: 15021.40Skamil validate_status_exited(status, exitval); 15031.40Skamil break; 15041.40Skamil default: 15051.40Skamil /* NOTREACHED */ 15061.40Skamil ATF_REQUIRE(0 && "NOT IMPLEMENTED"); 15071.40Skamil break; 15081.40Skamil } 15091.40Skamil 15101.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15111.40Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15121.40Skamil} 15131.40Skamil 15141.61Skre#define TRACEME_VFORK_RAISE(test, sig) \ 15151.61SkreATF_TC(test); \ 15161.61SkreATF_TC_HEAD(test, tc) \ 15171.61Skre{ \ 15181.61Skre atf_tc_set_md_var(tc, "descr", \ 15191.61Skre "Verify PT_TRACE_ME followed by raise of " #sig " in a " \ 15201.61Skre "vfork(2)ed child"); \ 15211.61Skre} \ 15221.61Skre \ 15231.61SkreATF_TC_BODY(test, tc) \ 15241.61Skre{ \ 15251.61Skre \ 15261.61Skre traceme_vfork_raise(sig); \ 15271.40Skamil} 15281.40Skamil 15291.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */ 15301.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */ 15311.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */ 15321.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */ 15331.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */ 15341.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */ 15351.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP) /* hangup */ 15361.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */ 15371.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */ 15381.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */ 15391.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */ 15401.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */ 15411.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */ 15421.40Skamil 15431.40Skamil/// ---------------------------------------------------------------------------- 15441.40Skamil 15451.52Skamilstatic void 15461.52Skamiltraceme_vfork_crash(int sig) 15471.41Skamil{ 15481.41Skamil pid_t child, wpid; 15491.41Skamil#if defined(TWAIT_HAVE_STATUS) 15501.41Skamil int status; 15511.41Skamil#endif 15521.41Skamil 15531.71Skamil#ifndef PTRACE_ILLEGAL_ASM 15541.71Skamil if (sig == SIGILL) 15551.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 15561.71Skamil#endif 15571.71Skamil 15581.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 15591.114Skamil atf_tc_skip("FP exceptions are not supported"); 15601.114Skamil 15611.41Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 15621.41Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 15631.41Skamil if (child == 0) { 15641.41Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 15651.41Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 15661.41Skamil 15671.52Skamil DPRINTF("Before executing a trap\n"); 15681.52Skamil switch (sig) { 15691.52Skamil case SIGTRAP: 15701.52Skamil trigger_trap(); 15711.52Skamil break; 15721.52Skamil case SIGSEGV: 15731.52Skamil trigger_segv(); 15741.52Skamil break; 15751.52Skamil case SIGILL: 15761.52Skamil trigger_ill(); 15771.52Skamil break; 15781.52Skamil case SIGFPE: 15791.52Skamil trigger_fpe(); 15801.52Skamil break; 15811.52Skamil case SIGBUS: 15821.52Skamil trigger_bus(); 15831.52Skamil break; 15841.52Skamil default: 15851.52Skamil /* NOTREACHED */ 15861.52Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15871.52Skamil } 15881.41Skamil 15891.41Skamil /* NOTREACHED */ 15901.41Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15911.41Skamil } 15921.41Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 15931.41Skamil 15941.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15951.41Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 15961.41Skamil 15971.52Skamil validate_status_signaled(status, sig, 1); 15981.41Skamil 15991.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16001.41Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 16011.41Skamil} 16021.41Skamil 16031.61Skre#define TRACEME_VFORK_CRASH(test, sig) \ 16041.61SkreATF_TC(test); \ 16051.61SkreATF_TC_HEAD(test, tc) \ 16061.61Skre{ \ 16071.61Skre atf_tc_set_md_var(tc, "descr", \ 16081.61Skre "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16091.61Skre "vfork(2)ed child"); \ 16101.61Skre} \ 16111.61Skre \ 16121.61SkreATF_TC_BODY(test, tc) \ 16131.61Skre{ \ 16141.61Skre \ 16151.61Skre traceme_vfork_crash(sig); \ 16161.52Skamil} 16171.52Skamil 16181.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP) 16191.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV) 16201.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL) 16211.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE) 16221.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS) 16231.52Skamil 16241.41Skamil/// ---------------------------------------------------------------------------- 16251.41Skamil 16261.92Skamilstatic void 16271.92Skamiltraceme_vfork_signalmasked_crash(int sig) 16281.92Skamil{ 16291.92Skamil pid_t child, wpid; 16301.92Skamil#if defined(TWAIT_HAVE_STATUS) 16311.92Skamil int status; 16321.92Skamil#endif 16331.92Skamil sigset_t intmask; 16341.92Skamil 16351.92Skamil#ifndef PTRACE_ILLEGAL_ASM 16361.92Skamil if (sig == SIGILL) 16371.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 16381.92Skamil#endif 16391.92Skamil 16401.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 16411.114Skamil atf_tc_skip("FP exceptions are not supported"); 16421.114Skamil 16431.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 16441.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 16451.92Skamil if (child == 0) { 16461.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 16471.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 16481.92Skamil 16491.92Skamil sigemptyset(&intmask); 16501.92Skamil sigaddset(&intmask, sig); 16511.92Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 16521.92Skamil 16531.92Skamil DPRINTF("Before executing a trap\n"); 16541.92Skamil switch (sig) { 16551.92Skamil case SIGTRAP: 16561.92Skamil trigger_trap(); 16571.92Skamil break; 16581.92Skamil case SIGSEGV: 16591.92Skamil trigger_segv(); 16601.92Skamil break; 16611.92Skamil case SIGILL: 16621.92Skamil trigger_ill(); 16631.92Skamil break; 16641.92Skamil case SIGFPE: 16651.92Skamil trigger_fpe(); 16661.92Skamil break; 16671.92Skamil case SIGBUS: 16681.92Skamil trigger_bus(); 16691.92Skamil break; 16701.92Skamil default: 16711.92Skamil /* NOTREACHED */ 16721.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16731.92Skamil } 16741.92Skamil 16751.92Skamil /* NOTREACHED */ 16761.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16771.92Skamil } 16781.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 16791.92Skamil 16801.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16811.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 16821.92Skamil 16831.92Skamil validate_status_signaled(status, sig, 1); 16841.92Skamil 16851.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16861.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 16871.92Skamil} 16881.92Skamil 16891.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig) \ 16901.92SkamilATF_TC(test); \ 16911.92SkamilATF_TC_HEAD(test, tc) \ 16921.92Skamil{ \ 16931.92Skamil atf_tc_set_md_var(tc, "descr", \ 16941.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16951.92Skamil "vfork(2)ed child with a masked signal"); \ 16961.92Skamil} \ 16971.92Skamil \ 16981.92SkamilATF_TC_BODY(test, tc) \ 16991.92Skamil{ \ 17001.92Skamil \ 17011.92Skamil traceme_vfork_signalmasked_crash(sig); \ 17021.92Skamil} 17031.92Skamil 17041.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP) 17051.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV) 17061.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL) 17071.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE) 17081.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS) 17091.92Skamil 17101.92Skamil/// ---------------------------------------------------------------------------- 17111.92Skamil 17121.92Skamilstatic void 17131.92Skamiltraceme_vfork_signalignored_crash(int sig) 17141.92Skamil{ 17151.92Skamil pid_t child, wpid; 17161.92Skamil#if defined(TWAIT_HAVE_STATUS) 17171.92Skamil int status; 17181.92Skamil#endif 17191.92Skamil struct sigaction sa; 17201.92Skamil 17211.92Skamil#ifndef PTRACE_ILLEGAL_ASM 17221.92Skamil if (sig == SIGILL) 17231.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 17241.92Skamil#endif 17251.92Skamil 17261.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 17271.114Skamil atf_tc_skip("FP exceptions are not supported"); 17281.114Skamil 17291.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 17301.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 17311.92Skamil if (child == 0) { 17321.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 17331.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 17341.92Skamil 17351.92Skamil memset(&sa, 0, sizeof(sa)); 17361.92Skamil sa.sa_handler = SIG_IGN; 17371.92Skamil sigemptyset(&sa.sa_mask); 17381.92Skamil 17391.92Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 17401.92Skamil 17411.92Skamil DPRINTF("Before executing a trap\n"); 17421.92Skamil switch (sig) { 17431.92Skamil case SIGTRAP: 17441.92Skamil trigger_trap(); 17451.92Skamil break; 17461.92Skamil case SIGSEGV: 17471.92Skamil trigger_segv(); 17481.92Skamil break; 17491.92Skamil case SIGILL: 17501.92Skamil trigger_ill(); 17511.92Skamil break; 17521.92Skamil case SIGFPE: 17531.92Skamil trigger_fpe(); 17541.92Skamil break; 17551.92Skamil case SIGBUS: 17561.92Skamil trigger_bus(); 17571.92Skamil break; 17581.92Skamil default: 17591.92Skamil /* NOTREACHED */ 17601.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17611.92Skamil } 17621.92Skamil 17631.92Skamil /* NOTREACHED */ 17641.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17651.92Skamil } 17661.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 17671.92Skamil 17681.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17691.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17701.92Skamil 17711.92Skamil validate_status_signaled(status, sig, 1); 17721.92Skamil 17731.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17741.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 17751.92Skamil} 17761.92Skamil 17771.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig) \ 17781.92SkamilATF_TC(test); \ 17791.92SkamilATF_TC_HEAD(test, tc) \ 17801.92Skamil{ \ 17811.92Skamil atf_tc_set_md_var(tc, "descr", \ 17821.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 17831.92Skamil "vfork(2)ed child with ignored signal"); \ 17841.92Skamil} \ 17851.92Skamil \ 17861.92SkamilATF_TC_BODY(test, tc) \ 17871.92Skamil{ \ 17881.92Skamil \ 17891.92Skamil traceme_vfork_signalignored_crash(sig); \ 17901.92Skamil} 17911.92Skamil 17921.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap, 17931.92Skamil SIGTRAP) 17941.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv, 17951.92Skamil SIGSEGV) 17961.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill, 17971.92Skamil SIGILL) 17981.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe, 17991.92Skamil SIGFPE) 18001.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus, 18011.92Skamil SIGBUS) 18021.92Skamil 18031.92Skamil/// ---------------------------------------------------------------------------- 18041.92Skamil 18051.96Skamilstatic void 18061.96Skamiltraceme_vfork_exec(bool masked, bool ignored) 18071.43Skamil{ 18081.43Skamil const int sigval = SIGTRAP; 18091.43Skamil pid_t child, wpid; 18101.43Skamil#if defined(TWAIT_HAVE_STATUS) 18111.43Skamil int status; 18121.43Skamil#endif 18131.96Skamil struct sigaction sa; 18141.61Skre struct ptrace_siginfo info; 18151.96Skamil sigset_t intmask; 18161.96Skamil struct kinfo_proc2 kp; 18171.96Skamil size_t len = sizeof(kp); 18181.96Skamil 18191.96Skamil int name[6]; 18201.96Skamil const size_t namelen = __arraycount(name); 18211.96Skamil ki_sigset_t kp_sigmask; 18221.96Skamil ki_sigset_t kp_sigignore; 18231.43Skamil 18241.43Skamil memset(&info, 0, sizeof(info)); 18251.43Skamil 18261.43Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 18271.43Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 18281.43Skamil if (child == 0) { 18291.43Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 18301.43Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 18311.43Skamil 18321.96Skamil if (masked) { 18331.96Skamil sigemptyset(&intmask); 18341.96Skamil sigaddset(&intmask, sigval); 18351.96Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 18361.96Skamil } 18371.96Skamil 18381.96Skamil if (ignored) { 18391.96Skamil memset(&sa, 0, sizeof(sa)); 18401.96Skamil sa.sa_handler = SIG_IGN; 18411.96Skamil sigemptyset(&sa.sa_mask); 18421.96Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 18431.96Skamil } 18441.96Skamil 18451.43Skamil DPRINTF("Before calling execve(2) from child\n"); 18461.43Skamil execlp("/bin/echo", "/bin/echo", NULL); 18471.43Skamil 18481.43Skamil /* NOTREACHED */ 18491.43Skamil FORKEE_ASSERTX(0 && "Not reached"); 18501.43Skamil } 18511.43Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 18521.43Skamil 18531.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 18541.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 18551.43Skamil 18561.43Skamil validate_status_stopped(status, sigval); 18571.43Skamil 18581.96Skamil name[0] = CTL_KERN, 18591.96Skamil name[1] = KERN_PROC2, 18601.96Skamil name[2] = KERN_PROC_PID; 18611.96Skamil name[3] = getpid(); 18621.96Skamil name[4] = sizeof(kp); 18631.96Skamil name[5] = 1; 18641.96Skamil 18651.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18661.96Skamil 18671.96Skamil if (masked) 18681.96Skamil kp_sigmask = kp.p_sigmask; 18691.96Skamil 18701.96Skamil if (ignored) 18711.96Skamil kp_sigignore = kp.p_sigignore; 18721.96Skamil 18731.96Skamil name[3] = getpid(); 18741.96Skamil 18751.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18761.96Skamil 18771.96Skamil if (masked) { 18781.96Skamil DPRINTF("kp_sigmask=" 18791.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18801.96Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 18811.96Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 18821.96Skamil 18831.96Skamil DPRINTF("kp.p_sigmask=" 18841.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18851.96Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 18861.96Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 18871.96Skamil 18881.96Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 18891.96Skamil sizeof(kp_sigmask))); 18901.96Skamil } 18911.96Skamil 18921.96Skamil if (ignored) { 18931.96Skamil DPRINTF("kp_sigignore=" 18941.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18951.96Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 18961.96Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 18971.96Skamil 18981.96Skamil DPRINTF("kp.p_sigignore=" 18991.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 19001.96Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 19011.96Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 19021.96Skamil 19031.96Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 19041.96Skamil sizeof(kp_sigignore))); 19051.96Skamil } 19061.96Skamil 19071.43Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 19081.61Skre SYSCALL_REQUIRE( 19091.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 19101.43Skamil 19111.43Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 19121.43Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 19131.43Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 19141.43Skamil info.psi_siginfo.si_errno); 19151.43Skamil 19161.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 19171.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 19181.43Skamil 19191.43Skamil DPRINTF("Before resuming the child process where it left off and " 19201.43Skamil "without signal to be sent\n"); 19211.43Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 19221.43Skamil 19231.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19241.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 19251.43Skamil 19261.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19271.43Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 19281.43Skamil} 19291.43Skamil 19301.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored) \ 19311.96SkamilATF_TC(test); \ 19321.96SkamilATF_TC_HEAD(test, tc) \ 19331.96Skamil{ \ 19341.96Skamil atf_tc_set_md_var(tc, "descr", \ 19351.96Skamil "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed " \ 19361.96Skamil "child%s%s", masked ? " with masked signal" : "", \ 19371.96Skamil masked ? " with ignored signal" : ""); \ 19381.96Skamil} \ 19391.96Skamil \ 19401.96SkamilATF_TC_BODY(test, tc) \ 19411.96Skamil{ \ 19421.96Skamil \ 19431.96Skamil traceme_vfork_exec(masked, ignored); \ 19441.96Skamil} 19451.96Skamil 19461.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false) 19471.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false) 19481.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true) 19491.96Skamil 19501.43Skamil/// ---------------------------------------------------------------------------- 19511.43Skamil 19521.1Skamil#if defined(TWAIT_HAVE_PID) 19531.51Skamilstatic void 19541.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored) 19551.59Skamil{ 19561.94Skamil const int sigval = SIGSTOP; 19571.59Skamil struct msg_fds parent_tracee, parent_tracer; 19581.59Skamil const int exitval = 10; 19591.59Skamil pid_t tracee, tracer, wpid; 19601.59Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 19611.59Skamil#if defined(TWAIT_HAVE_STATUS) 19621.59Skamil int status; 19631.59Skamil#endif 19641.94Skamil struct sigaction sa; 19651.59Skamil struct ptrace_siginfo info; 19661.94Skamil sigset_t intmask; 19671.94Skamil struct kinfo_proc2 kp; 19681.94Skamil size_t len = sizeof(kp); 19691.94Skamil 19701.94Skamil int name[6]; 19711.94Skamil const size_t namelen = __arraycount(name); 19721.94Skamil ki_sigset_t kp_sigmask; 19731.94Skamil ki_sigset_t kp_sigignore; 19741.61Skre 19751.71Skamil#ifndef PTRACE_ILLEGAL_ASM 19761.71Skamil if (sig == SIGILL) 19771.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 19781.71Skamil#endif 19791.71Skamil 19801.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 19811.114Skamil atf_tc_skip("FP exceptions are not supported"); 19821.114Skamil 19831.59Skamil memset(&info, 0, sizeof(info)); 19841.59Skamil 19851.59Skamil DPRINTF("Spawn tracee\n"); 19861.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 19871.59Skamil tracee = atf_utils_fork(); 19881.59Skamil if (tracee == 0) { 19891.59Skamil // Wait for parent to let us crash 19901.59Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 19911.61Skre 19921.94Skamil if (masked) { 19931.94Skamil sigemptyset(&intmask); 19941.94Skamil sigaddset(&intmask, sig); 19951.94Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 19961.94Skamil } 19971.94Skamil 19981.94Skamil if (ignored) { 19991.94Skamil memset(&sa, 0, sizeof(sa)); 20001.94Skamil sa.sa_handler = SIG_IGN; 20011.94Skamil sigemptyset(&sa.sa_mask); 20021.94Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 20031.94Skamil } 20041.94Skamil 20051.94Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 20061.94Skamil FORKEE_ASSERT(raise(sigval) == 0); 20071.94Skamil 20081.59Skamil DPRINTF("Before executing a trap\n"); 20091.59Skamil switch (sig) { 20101.59Skamil case SIGTRAP: 20111.59Skamil trigger_trap(); 20121.59Skamil break; 20131.59Skamil case SIGSEGV: 20141.59Skamil trigger_segv(); 20151.59Skamil break; 20161.59Skamil case SIGILL: 20171.59Skamil trigger_ill(); 20181.59Skamil break; 20191.59Skamil case SIGFPE: 20201.59Skamil trigger_fpe(); 20211.59Skamil break; 20221.59Skamil case SIGBUS: 20231.59Skamil trigger_bus(); 20241.59Skamil break; 20251.59Skamil default: 20261.59Skamil /* NOTREACHED */ 20271.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20281.59Skamil } 20291.59Skamil 20301.59Skamil /* NOTREACHED */ 20311.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20321.59Skamil } 20331.59Skamil 20341.59Skamil DPRINTF("Spawn debugger\n"); 20351.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 20361.59Skamil tracer = atf_utils_fork(); 20371.59Skamil if (tracer == 0) { 20381.59Skamil /* Fork again and drop parent to reattach to PID 1 */ 20391.59Skamil tracer = atf_utils_fork(); 20401.59Skamil if (tracer != 0) 20411.61Skre _exit(exitval); 20421.59Skamil 20431.59Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 20441.59Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 20451.59Skamil 20461.59Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 20471.59Skamil FORKEE_REQUIRE_SUCCESS( 20481.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20491.59Skamil 20501.59Skamil forkee_status_stopped(status, SIGSTOP); 20511.59Skamil 20521.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20531.94Skamil "traced process\n"); 20541.94Skamil SYSCALL_REQUIRE( 20551.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20561.94Skamil 20571.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20581.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20591.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20601.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20611.94Skamil 20621.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 20631.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 20641.94Skamil 20651.59Skamil /* Resume tracee with PT_CONTINUE */ 20661.59Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 20671.59Skamil 20681.59Skamil /* Inform parent that tracer has attached to tracee */ 20691.59Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 20701.59Skamil 20711.59Skamil /* Wait for parent to tell use that tracee should have exited */ 20721.59Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 20731.59Skamil 20741.59Skamil /* Wait for tracee and assert that it exited */ 20751.59Skamil FORKEE_REQUIRE_SUCCESS( 20761.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20771.59Skamil 20781.94Skamil forkee_status_stopped(status, sigval); 20791.94Skamil 20801.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20811.94Skamil "traced process\n"); 20821.94Skamil SYSCALL_REQUIRE( 20831.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20841.94Skamil 20851.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20861.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20871.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20881.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20891.94Skamil 20901.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 20911.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 20921.94Skamil 20931.94Skamil name[0] = CTL_KERN, 20941.94Skamil name[1] = KERN_PROC2, 20951.94Skamil name[2] = KERN_PROC_PID; 20961.94Skamil name[3] = tracee; 20971.94Skamil name[4] = sizeof(kp); 20981.94Skamil name[5] = 1; 20991.94Skamil 21001.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21011.94Skamil 21021.94Skamil if (masked) 21031.94Skamil kp_sigmask = kp.p_sigmask; 21041.94Skamil 21051.94Skamil if (ignored) 21061.94Skamil kp_sigignore = kp.p_sigignore; 21071.94Skamil 21081.94Skamil /* Resume tracee with PT_CONTINUE */ 21091.94Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 21101.94Skamil 21111.94Skamil /* Wait for tracee and assert that it exited */ 21121.94Skamil FORKEE_REQUIRE_SUCCESS( 21131.94Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21141.94Skamil 21151.93Skamil forkee_status_stopped(status, sig); 21161.59Skamil 21171.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 21181.61Skre "traced process\n"); 21191.61Skre SYSCALL_REQUIRE( 21201.61Skre ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 21211.59Skamil 21221.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21231.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21241.61Skre "si_errno=%#x\n", info.psi_siginfo.si_signo, 21251.61Skre info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 21261.59Skamil 21271.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig); 21281.94Skamil 21291.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21301.94Skamil 21311.94Skamil if (masked) { 21321.94Skamil DPRINTF("kp_sigmask=" 21331.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21341.94Skamil PRIx32 "\n", 21351.94Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 21361.94Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 21371.94Skamil 21381.94Skamil DPRINTF("kp.p_sigmask=" 21391.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21401.94Skamil PRIx32 "\n", 21411.94Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 21421.94Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 21431.94Skamil 21441.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask, 21451.94Skamil sizeof(kp_sigmask))); 21461.94Skamil } 21471.94Skamil 21481.94Skamil if (ignored) { 21491.94Skamil DPRINTF("kp_sigignore=" 21501.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21511.94Skamil PRIx32 "\n", 21521.94Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 21531.94Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 21541.94Skamil 21551.94Skamil DPRINTF("kp.p_sigignore=" 21561.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21571.94Skamil PRIx32 "\n", 21581.94Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 21591.94Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 21601.94Skamil 21611.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore, 21621.94Skamil sizeof(kp_sigignore))); 21631.94Skamil } 21641.94Skamil 21651.59Skamil switch (sig) { 21661.59Skamil case SIGTRAP: 21671.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 21681.59Skamil break; 21691.59Skamil case SIGSEGV: 21701.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 21711.59Skamil break; 21721.71Skamil case SIGILL: 21731.113Skamil FORKEE_ASSERT(info.psi_siginfo.si_code >= ILL_ILLOPC && 21741.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 21751.71Skamil break; 21761.59Skamil case SIGFPE: 21771.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 21781.59Skamil break; 21791.59Skamil case SIGBUS: 21801.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 21811.59Skamil break; 21821.59Skamil } 21831.59Skamil 21841.59Skamil FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1); 21851.59Skamil DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME); 21861.93Skamil FORKEE_REQUIRE_SUCCESS( 21871.61Skre wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21881.59Skamil 21891.93Skamil forkee_status_signaled(status, SIGKILL, 0); 21901.59Skamil 21911.71Skamil /* Inform parent that tracer is exiting normally */ 21921.71Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 21931.71Skamil 21941.59Skamil DPRINTF("Before exiting of the tracer process\n"); 21951.59Skamil _exit(0 /* collect by initproc */); 21961.59Skamil } 21971.59Skamil 21981.59Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 21991.59Skamil "calling %s()\n", TWAIT_FNAME); 22001.59Skamil TWAIT_REQUIRE_SUCCESS( 22011.59Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 22021.59Skamil 22031.59Skamil validate_status_exited(status, exitval); 22041.59Skamil 22051.59Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 22061.59Skamil TWAIT_FNAME); 22071.59Skamil TWAIT_REQUIRE_SUCCESS( 22081.59Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 22091.59Skamil 22101.59Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 22111.59Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 22121.59Skamil 22131.59Skamil DPRINTF("Resume the tracee and let it crash\n"); 22141.59Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 22151.59Skamil 22161.59Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 22171.59Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 22181.59Skamil 22191.59Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 22201.59Skamil TWAIT_FNAME); 22211.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22221.59Skamil 22231.59Skamil validate_status_signaled(status, SIGKILL, 0); 22241.59Skamil 22251.71Skamil DPRINTF("Await normal exit of tracer\n"); 22261.71Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 22271.71Skamil 22281.59Skamil msg_close(&parent_tracer); 22291.59Skamil msg_close(&parent_tracee); 22301.59Skamil} 22311.59Skamil 22321.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig) \ 22331.61SkreATF_TC(test); \ 22341.61SkreATF_TC_HEAD(test, tc) \ 22351.61Skre{ \ 22361.61Skre atf_tc_set_md_var(tc, "descr", \ 22371.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22381.94Skamil "the debuggee"); \ 22391.61Skre} \ 22401.61Skre \ 22411.61SkreATF_TC_BODY(test, tc) \ 22421.61Skre{ \ 22431.61Skre \ 22441.94Skamil unrelated_tracer_sees_crash(sig, false, false); \ 22451.59Skamil} 22461.59Skamil 22471.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP) 22481.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV) 22491.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL) 22501.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE) 22511.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS) 22521.94Skamil 22531.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig) \ 22541.94SkamilATF_TC(test); \ 22551.94SkamilATF_TC_HEAD(test, tc) \ 22561.94Skamil{ \ 22571.94Skamil atf_tc_set_md_var(tc, "descr", \ 22581.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22591.94Skamil "the debuggee with masked signal"); \ 22601.94Skamil} \ 22611.94Skamil \ 22621.94SkamilATF_TC_BODY(test, tc) \ 22631.94Skamil{ \ 22641.94Skamil \ 22651.94Skamil unrelated_tracer_sees_crash(sig, true, false); \ 22661.94Skamil} 22671.94Skamil 22681.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22691.94Skamil unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP) 22701.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22711.94Skamil unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV) 22721.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22731.94Skamil unrelated_tracer_sees_signalmasked_crash_ill, SIGILL) 22741.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22751.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE) 22761.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22771.94Skamil unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS) 22781.94Skamil 22791.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig) \ 22801.94SkamilATF_TC(test); \ 22811.94SkamilATF_TC_HEAD(test, tc) \ 22821.94Skamil{ \ 22831.94Skamil atf_tc_set_md_var(tc, "descr", \ 22841.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22851.94Skamil "the debuggee with signal ignored"); \ 22861.94Skamil} \ 22871.94Skamil \ 22881.94SkamilATF_TC_BODY(test, tc) \ 22891.94Skamil{ \ 22901.94Skamil \ 22911.94Skamil unrelated_tracer_sees_crash(sig, false, true); \ 22921.94Skamil} 22931.94Skamil 22941.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22951.94Skamil unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP) 22961.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22971.94Skamil unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV) 22981.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22991.94Skamil unrelated_tracer_sees_signalignored_crash_ill, SIGILL) 23001.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23011.94Skamil unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE) 23021.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23031.94Skamil unrelated_tracer_sees_signalignored_crash_bus, SIGBUS) 23041.59Skamil#endif 23051.59Skamil 23061.59Skamil/// ---------------------------------------------------------------------------- 23071.59Skamil 23081.59Skamil#if defined(TWAIT_HAVE_PID) 23091.59Skamilstatic void 23101.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated, 23111.67Skamil bool stopped) 23121.1Skamil{ 23131.51Skamil /* 23141.51Skamil * notimeout - disable timeout in await zombie function 23151.51Skamil * unrelated - attach from unrelated tracer reparented to initproc 23161.67Skamil * stopped - attach to a stopped process 23171.51Skamil */ 23181.1Skamil 23191.1Skamil struct msg_fds parent_tracee, parent_tracer; 23201.1Skamil const int exitval_tracee = 5; 23211.1Skamil const int exitval_tracer = 10; 23221.1Skamil pid_t tracee, tracer, wpid; 23231.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 23241.1Skamil#if defined(TWAIT_HAVE_STATUS) 23251.1Skamil int status; 23261.1Skamil#endif 23271.1Skamil 23281.67Skamil /* 23291.67Skamil * Only a subset of options are supported. 23301.67Skamil */ 23311.67Skamil ATF_REQUIRE((!notimeout && !unrelated && !stopped) || 23321.67Skamil (!notimeout && unrelated && !stopped) || 23331.67Skamil (notimeout && !unrelated && !stopped) || 23341.67Skamil (!notimeout && unrelated && stopped)); 23351.67Skamil 23361.13Schristos DPRINTF("Spawn tracee\n"); 23371.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 23381.1Skamil tracee = atf_utils_fork(); 23391.1Skamil if (tracee == 0) { 23401.67Skamil if (stopped) { 23411.67Skamil DPRINTF("Stop self PID %d\n", getpid()); 23421.67Skamil raise(SIGSTOP); 23431.67Skamil } 23441.67Skamil 23451.1Skamil // Wait for parent to let us exit 23461.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 23471.1Skamil _exit(exitval_tracee); 23481.1Skamil } 23491.1Skamil 23501.13Schristos DPRINTF("Spawn debugger\n"); 23511.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 23521.1Skamil tracer = atf_utils_fork(); 23531.1Skamil if (tracer == 0) { 23541.51Skamil if(unrelated) { 23551.51Skamil /* Fork again and drop parent to reattach to PID 1 */ 23561.51Skamil tracer = atf_utils_fork(); 23571.51Skamil if (tracer != 0) 23581.51Skamil _exit(exitval_tracer); 23591.51Skamil } 23601.51Skamil 23611.67Skamil if (stopped) { 23621.67Skamil DPRINTF("Await for a stopped parent PID %d\n", tracee); 23631.67Skamil await_stopped(tracee); 23641.67Skamil } 23651.67Skamil 23661.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 23671.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 23681.1Skamil 23691.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 23701.1Skamil FORKEE_REQUIRE_SUCCESS( 23711.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23721.1Skamil 23731.1Skamil forkee_status_stopped(status, SIGSTOP); 23741.1Skamil 23751.1Skamil /* Resume tracee with PT_CONTINUE */ 23761.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 23771.1Skamil 23781.1Skamil /* Inform parent that tracer has attached to tracee */ 23791.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 23801.1Skamil 23811.1Skamil /* Wait for parent to tell use that tracee should have exited */ 23821.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 23831.1Skamil 23841.1Skamil /* Wait for tracee and assert that it exited */ 23851.1Skamil FORKEE_REQUIRE_SUCCESS( 23861.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23871.1Skamil 23881.1Skamil forkee_status_exited(status, exitval_tracee); 23891.13Schristos DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee); 23901.1Skamil 23911.13Schristos DPRINTF("Before exiting of the tracer process\n"); 23921.51Skamil _exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer); 23931.51Skamil } 23941.51Skamil 23951.51Skamil if (unrelated) { 23961.51Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 23971.51Skamil "calling %s()\n", TWAIT_FNAME); 23981.51Skamil TWAIT_REQUIRE_SUCCESS( 23991.51Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 24001.51Skamil 24011.51Skamil validate_status_exited(status, exitval_tracer); 24021.51Skamil 24031.51Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 24041.51Skamil TWAIT_FNAME); 24051.51Skamil TWAIT_REQUIRE_SUCCESS( 24061.51Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 24071.1Skamil } 24081.1Skamil 24091.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 24101.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 24111.1Skamil 24121.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 24131.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 24141.1Skamil 24151.13Schristos DPRINTF("Detect that tracee is zombie\n"); 24161.51Skamil if (notimeout) 24171.26Skamil await_zombie_raw(tracee, 0); 24181.26Skamil else 24191.26Skamil await_zombie(tracee); 24201.1Skamil 24211.13Schristos DPRINTF("Assert that there is no status about tracee %d - " 24221.1Skamil "Tracer must detect zombie first - calling %s()\n", tracee, 24231.1Skamil TWAIT_FNAME); 24241.1Skamil TWAIT_REQUIRE_SUCCESS( 24251.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 24261.1Skamil 24271.51Skamil if (unrelated) { 24281.51Skamil DPRINTF("Resume the tracer and let it detect exited tracee\n"); 24291.51Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 24301.51Skamil } else { 24311.51Skamil DPRINTF("Tell the tracer child should have exited\n"); 24321.51Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 24331.51Skamil DPRINTF("Wait for tracer to finish its job and exit - calling " 24341.59Skamil "%s()\n", TWAIT_FNAME); 24351.51Skamil 24361.51Skamil DPRINTF("Wait from tracer child to complete waiting for " 24371.59Skamil "tracee\n"); 24381.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 24391.51Skamil tracer); 24401.1Skamil 24411.51Skamil validate_status_exited(status, exitval_tracer); 24421.51Skamil } 24431.1Skamil 24441.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 24451.1Skamil TWAIT_FNAME); 24461.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24471.1Skamil 24481.1Skamil validate_status_exited(status, exitval_tracee); 24491.1Skamil 24501.1Skamil msg_close(&parent_tracer); 24511.1Skamil msg_close(&parent_tracee); 24521.1Skamil} 24531.26Skamil 24541.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent); 24551.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc) 24561.51Skamil{ 24571.51Skamil atf_tc_set_md_var(tc, "descr", 24581.51Skamil "Assert that tracer sees process termination before the parent"); 24591.51Skamil} 24601.51Skamil 24611.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc) 24621.26Skamil{ 24631.26Skamil 24641.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, false, false); 24651.26Skamil} 24661.26Skamil 24671.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates); 24681.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc) 24691.1Skamil{ 24701.1Skamil atf_tc_set_md_var(tc, "descr", 24711.51Skamil "Assert that await_zombie() in attach1 always finds a single " 24721.51Skamil "process and no other error is reported"); 24731.1Skamil} 24741.1Skamil 24751.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc) 24761.1Skamil{ 24771.51Skamil time_t start, end; 24781.51Skamil double diff; 24791.51Skamil unsigned long N = 0; 24801.1Skamil 24811.51Skamil /* 24821.51Skamil * Reuse this test with tracer_sees_terminaton_before_the_parent_raw(). 24831.51Skamil * This test body isn't specific to this race, however it's just good 24841.51Skamil * enough for this purposes, no need to invent a dedicated code flow. 24851.51Skamil */ 24861.1Skamil 24871.51Skamil start = time(NULL); 24881.51Skamil while (true) { 24891.51Skamil DPRINTF("Step: %lu\n", N); 24901.67Skamil tracer_sees_terminaton_before_the_parent_raw(true, false, 24911.67Skamil false); 24921.51Skamil end = time(NULL); 24931.51Skamil diff = difftime(end, start); 24941.51Skamil if (diff >= 5.0) 24951.51Skamil break; 24961.51Skamil ++N; 24971.1Skamil } 24981.51Skamil DPRINTF("Iterations: %lu\n", N); 24991.51Skamil} 25001.1Skamil 25011.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent); 25021.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc) 25031.51Skamil{ 25041.51Skamil atf_tc_set_md_var(tc, "descr", 25051.51Skamil "Assert that tracer sees process termination before the parent"); 25061.51Skamil} 25071.1Skamil 25081.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc) 25091.51Skamil{ 25101.1Skamil 25111.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, false); 25121.67Skamil} 25131.67Skamil 25141.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process); 25151.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc) 25161.67Skamil{ 25171.67Skamil atf_tc_set_md_var(tc, "descr", 25181.67Skamil "Assert that tracer can attach to an unrelated stopped process"); 25191.67Skamil} 25201.67Skamil 25211.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc) 25221.67Skamil{ 25231.67Skamil 25241.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, true); 25251.1Skamil} 25261.1Skamil#endif 25271.1Skamil 25281.51Skamil/// ---------------------------------------------------------------------------- 25291.51Skamil 25301.66Skamilstatic void 25311.66Skamilparent_attach_to_its_child(bool stopped) 25321.1Skamil{ 25331.1Skamil struct msg_fds parent_tracee; 25341.1Skamil const int exitval_tracee = 5; 25351.1Skamil pid_t tracee, wpid; 25361.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 25371.1Skamil#if defined(TWAIT_HAVE_STATUS) 25381.1Skamil int status; 25391.1Skamil#endif 25401.1Skamil 25411.13Schristos DPRINTF("Spawn tracee\n"); 25421.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 25431.1Skamil tracee = atf_utils_fork(); 25441.1Skamil if (tracee == 0) { 25451.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 25461.13Schristos DPRINTF("Parent should now attach to tracee\n"); 25471.1Skamil 25481.66Skamil if (stopped) { 25491.66Skamil DPRINTF("Stop self PID %d\n", getpid()); 25501.66Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 25511.66Skamil } 25521.66Skamil 25531.1Skamil CHILD_FROM_PARENT("Message 2", parent_tracee, msg); 25541.1Skamil /* Wait for message from the parent */ 25551.1Skamil _exit(exitval_tracee); 25561.1Skamil } 25571.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 25581.57Skamil 25591.66Skamil if (stopped) { 25601.66Skamil DPRINTF("Await for a stopped tracee PID %d\n", tracee); 25611.66Skamil await_stopped(tracee); 25621.66Skamil } 25631.66Skamil 25641.13Schristos DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee); 25651.13Schristos SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 25661.1Skamil 25671.13Schristos DPRINTF("Wait for the stopped tracee process with %s()\n", 25681.1Skamil TWAIT_FNAME); 25691.1Skamil TWAIT_REQUIRE_SUCCESS( 25701.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25711.1Skamil 25721.1Skamil validate_status_stopped(status, SIGSTOP); 25731.1Skamil 25741.13Schristos DPRINTF("Resume tracee with PT_CONTINUE\n"); 25751.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 25761.1Skamil 25771.13Schristos DPRINTF("Let the tracee exit now\n"); 25781.1Skamil PARENT_TO_CHILD("Message 2", parent_tracee, msg); 25791.1Skamil 25801.13Schristos DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME); 25811.1Skamil TWAIT_REQUIRE_SUCCESS( 25821.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25831.1Skamil 25841.1Skamil validate_status_exited(status, exitval_tracee); 25851.1Skamil 25861.13Schristos DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME); 25871.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 25881.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0)); 25891.1Skamil 25901.1Skamil msg_close(&parent_tracee); 25911.1Skamil} 25921.1Skamil 25931.66SkamilATF_TC(parent_attach_to_its_child); 25941.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc) 25951.66Skamil{ 25961.66Skamil atf_tc_set_md_var(tc, "descr", 25971.66Skamil "Assert that tracer parent can PT_ATTACH to its child"); 25981.66Skamil} 25991.66Skamil 26001.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc) 26011.66Skamil{ 26021.66Skamil 26031.66Skamil parent_attach_to_its_child(false); 26041.66Skamil} 26051.66Skamil 26061.66SkamilATF_TC(parent_attach_to_its_stopped_child); 26071.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc) 26081.66Skamil{ 26091.66Skamil atf_tc_set_md_var(tc, "descr", 26101.66Skamil "Assert that tracer parent can PT_ATTACH to its stopped child"); 26111.66Skamil} 26121.66Skamil 26131.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc) 26141.66Skamil{ 26151.66Skamil 26161.66Skamil parent_attach_to_its_child(true); 26171.66Skamil} 26181.66Skamil 26191.51Skamil/// ---------------------------------------------------------------------------- 26201.51Skamil 26211.65Skamilstatic void 26221.65Skamilchild_attach_to_its_parent(bool stopped) 26231.1Skamil{ 26241.1Skamil struct msg_fds parent_tracee; 26251.1Skamil const int exitval_tracer = 5; 26261.1Skamil pid_t tracer, wpid; 26271.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 26281.1Skamil#if defined(TWAIT_HAVE_STATUS) 26291.1Skamil int status; 26301.1Skamil#endif 26311.1Skamil 26321.13Schristos DPRINTF("Spawn tracer\n"); 26331.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 26341.1Skamil tracer = atf_utils_fork(); 26351.1Skamil if (tracer == 0) { 26361.1Skamil /* Wait for message from the parent */ 26371.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 26381.1Skamil 26391.65Skamil if (stopped) { 26401.65Skamil DPRINTF("Await for a stopped parent PID %d\n", 26411.65Skamil getppid()); 26421.65Skamil await_stopped(getppid()); 26431.65Skamil } 26441.65Skamil 26451.13Schristos DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n", 26461.1Skamil getppid()); 26471.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1); 26481.1Skamil 26491.13Schristos DPRINTF("Wait for the stopped parent process with %s()\n", 26501.1Skamil TWAIT_FNAME); 26511.1Skamil FORKEE_REQUIRE_SUCCESS( 26521.1Skamil wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid()); 26531.1Skamil 26541.1Skamil forkee_status_stopped(status, SIGSTOP); 26551.1Skamil 26561.13Schristos DPRINTF("Resume parent with PT_DETACH\n"); 26571.1Skamil FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0) 26581.1Skamil != -1); 26591.1Skamil 26601.1Skamil /* Tell parent we are ready */ 26611.1Skamil CHILD_TO_PARENT("Message 1", parent_tracee, msg); 26621.1Skamil 26631.1Skamil _exit(exitval_tracer); 26641.1Skamil } 26651.1Skamil 26661.13Schristos DPRINTF("Wait for the tracer to become ready\n"); 26671.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 26681.65Skamil 26691.65Skamil if (stopped) { 26701.65Skamil DPRINTF("Stop self PID %d\n", getpid()); 26711.65Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 26721.65Skamil } 26731.65Skamil 26741.13Schristos DPRINTF("Allow the tracer to exit now\n"); 26751.1Skamil PARENT_FROM_CHILD("Message 1", parent_tracee, msg); 26761.1Skamil 26771.13Schristos DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME); 26781.1Skamil TWAIT_REQUIRE_SUCCESS( 26791.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 26801.1Skamil 26811.1Skamil validate_status_exited(status, exitval_tracer); 26821.1Skamil 26831.13Schristos DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME); 26841.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 26851.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0)); 26861.1Skamil 26871.1Skamil msg_close(&parent_tracee); 26881.1Skamil} 26891.1Skamil 26901.65SkamilATF_TC(child_attach_to_its_parent); 26911.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc) 26921.65Skamil{ 26931.65Skamil atf_tc_set_md_var(tc, "descr", 26941.65Skamil "Assert that tracer child can PT_ATTACH to its parent"); 26951.65Skamil} 26961.65Skamil 26971.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc) 26981.65Skamil{ 26991.65Skamil 27001.65Skamil child_attach_to_its_parent(false); 27011.65Skamil} 27021.65Skamil 27031.65SkamilATF_TC(child_attach_to_its_stopped_parent); 27041.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc) 27051.65Skamil{ 27061.65Skamil atf_tc_set_md_var(tc, "descr", 27071.65Skamil "Assert that tracer child can PT_ATTACH to its stopped parent"); 27081.65Skamil} 27091.65Skamil 27101.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc) 27111.65Skamil{ 27121.65Skamil /* 27131.65Skamil * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as 27141.65Skamil * this causes a pipe (established from atf-run) to be broken. 27151.65Skamil * atf-run uses this mechanism to monitor whether a test is alive. 27161.65Skamil * 27171.65Skamil * As a workaround spawn this test as a subprocess. 27181.65Skamil */ 27191.65Skamil 27201.65Skamil const int exitval = 15; 27211.65Skamil pid_t child, wpid; 27221.65Skamil#if defined(TWAIT_HAVE_STATUS) 27231.65Skamil int status; 27241.65Skamil#endif 27251.65Skamil 27261.65Skamil SYSCALL_REQUIRE((child = fork()) != -1); 27271.65Skamil if (child == 0) { 27281.65Skamil child_attach_to_its_parent(true); 27291.65Skamil _exit(exitval); 27301.65Skamil } else { 27311.65Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 27321.65Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 27331.65Skamil 27341.65Skamil validate_status_exited(status, exitval); 27351.65Skamil 27361.65Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 27371.65Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 27381.65Skamil } 27391.65Skamil} 27401.65Skamil 27411.51Skamil/// ---------------------------------------------------------------------------- 27421.51Skamil 27431.1Skamil#if defined(TWAIT_HAVE_PID) 27441.1Skamil 27451.51Skamilenum tracee_sees_its_original_parent_type { 27461.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 27471.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 27481.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS 27491.51Skamil}; 27501.51Skamil 27511.51Skamilstatic void 27521.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type) 27531.1Skamil{ 27541.1Skamil struct msg_fds parent_tracer, parent_tracee; 27551.1Skamil const int exitval_tracee = 5; 27561.1Skamil const int exitval_tracer = 10; 27571.1Skamil pid_t parent, tracee, tracer, wpid; 27581.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 27591.1Skamil#if defined(TWAIT_HAVE_STATUS) 27601.1Skamil int status; 27611.1Skamil#endif 27621.51Skamil /* sysctl(3) - kinfo_proc2 */ 27631.51Skamil int name[CTL_MAXNAME]; 27641.51Skamil struct kinfo_proc2 kp; 27651.51Skamil size_t len = sizeof(kp); 27661.51Skamil unsigned int namelen; 27671.51Skamil 27681.51Skamil /* procfs - status */ 27691.51Skamil FILE *fp; 27701.51Skamil struct stat st; 27711.51Skamil const char *fname = "/proc/curproc/status"; 27721.51Skamil char s_executable[MAXPATHLEN]; 27731.51Skamil int s_pid, s_ppid; 27741.51Skamil int rv; 27751.51Skamil 27761.51Skamil if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) { 27771.61Skre SYSCALL_REQUIRE( 27781.61Skre (rv = stat(fname, &st)) == 0 || (errno == ENOENT)); 27791.61Skre if (rv != 0) 27801.51Skamil atf_tc_skip("/proc/curproc/status not found"); 27811.51Skamil } 27821.1Skamil 27831.13Schristos DPRINTF("Spawn tracee\n"); 27841.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 27851.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 27861.1Skamil tracee = atf_utils_fork(); 27871.1Skamil if (tracee == 0) { 27881.1Skamil parent = getppid(); 27891.1Skamil 27901.1Skamil /* Emit message to the parent */ 27911.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 27921.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 27931.1Skamil 27941.51Skamil switch (type) { 27951.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID: 27961.51Skamil FORKEE_ASSERT_EQ(parent, getppid()); 27971.51Skamil break; 27981.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2: 27991.51Skamil namelen = 0; 28001.51Skamil name[namelen++] = CTL_KERN; 28011.51Skamil name[namelen++] = KERN_PROC2; 28021.51Skamil name[namelen++] = KERN_PROC_PID; 28031.51Skamil name[namelen++] = getpid(); 28041.51Skamil name[namelen++] = len; 28051.51Skamil name[namelen++] = 1; 28061.51Skamil 28071.61Skre FORKEE_ASSERT_EQ( 28081.61Skre sysctl(name, namelen, &kp, &len, NULL, 0), 0); 28091.51Skamil FORKEE_ASSERT_EQ(parent, kp.p_ppid); 28101.51Skamil break; 28111.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS: 28121.51Skamil /* 28131.51Skamil * Format: 28141.51Skamil * EXECUTABLE PID PPID ... 28151.51Skamil */ 28161.51Skamil FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL); 28171.51Skamil fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid); 28181.51Skamil FORKEE_ASSERT_EQ(fclose(fp), 0); 28191.51Skamil FORKEE_ASSERT_EQ(parent, s_ppid); 28201.51Skamil break; 28211.51Skamil } 28221.1Skamil 28231.1Skamil _exit(exitval_tracee); 28241.1Skamil } 28251.13Schristos DPRINTF("Wait for child to record its parent identifier (pid)\n"); 28261.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 28271.1Skamil 28281.13Schristos DPRINTF("Spawn debugger\n"); 28291.1Skamil tracer = atf_utils_fork(); 28301.1Skamil if (tracer == 0) { 28311.1Skamil /* No IPC to communicate with the child */ 28321.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 28331.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 28341.1Skamil 28351.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 28361.1Skamil FORKEE_REQUIRE_SUCCESS( 28371.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28381.1Skamil 28391.1Skamil forkee_status_stopped(status, SIGSTOP); 28401.1Skamil 28411.1Skamil /* Resume tracee with PT_CONTINUE */ 28421.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 28431.1Skamil 28441.1Skamil /* Inform parent that tracer has attached to tracee */ 28451.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 28461.1Skamil 28471.1Skamil /* Wait for parent to tell use that tracee should have exited */ 28481.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 28491.1Skamil 28501.1Skamil /* Wait for tracee and assert that it exited */ 28511.1Skamil FORKEE_REQUIRE_SUCCESS( 28521.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28531.1Skamil 28541.1Skamil forkee_status_exited(status, exitval_tracee); 28551.1Skamil 28561.13Schristos DPRINTF("Before exiting of the tracer process\n"); 28571.1Skamil _exit(exitval_tracer); 28581.1Skamil } 28591.1Skamil 28601.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 28611.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 28621.1Skamil 28631.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 28641.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 28651.1Skamil 28661.13Schristos DPRINTF("Detect that tracee is zombie\n"); 28671.1Skamil await_zombie(tracee); 28681.1Skamil 28691.13Schristos DPRINTF("Assert that there is no status about tracee - " 28701.1Skamil "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME); 28711.1Skamil TWAIT_REQUIRE_SUCCESS( 28721.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 28731.1Skamil 28741.13Schristos DPRINTF("Tell the tracer child should have exited\n"); 28751.1Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 28761.1Skamil 28771.13Schristos DPRINTF("Wait from tracer child to complete waiting for tracee\n"); 28781.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 28791.1Skamil tracer); 28801.1Skamil 28811.1Skamil validate_status_exited(status, exitval_tracer); 28821.1Skamil 28831.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 28841.1Skamil TWAIT_FNAME); 28851.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 28861.1Skamil tracee); 28871.1Skamil 28881.1Skamil validate_status_exited(status, exitval_tracee); 28891.1Skamil 28901.1Skamil msg_close(&parent_tracer); 28911.1Skamil msg_close(&parent_tracee); 28921.1Skamil} 28931.1Skamil 28941.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr) \ 28951.61SkreATF_TC(test); \ 28961.61SkreATF_TC_HEAD(test, tc) \ 28971.61Skre{ \ 28981.61Skre atf_tc_set_md_var(tc, "descr", \ 28991.61Skre "Assert that tracee sees its original parent when being traced " \ 29001.61Skre "(check " descr ")"); \ 29011.61Skre} \ 29021.61Skre \ 29031.61SkreATF_TC_BODY(test, tc) \ 29041.61Skre{ \ 29051.61Skre \ 29061.61Skre tracee_sees_its_original_parent(type); \ 29071.1Skamil} 29081.1Skamil 29091.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29101.51Skamil tracee_sees_its_original_parent_getppid, 29111.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 29121.51Skamil "getppid(2)"); 29131.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29141.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2, 29151.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 29161.51Skamil "sysctl(3) and kinfo_proc2"); 29171.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29181.51Skamil tracee_sees_its_original_parent_procfs_status, 29191.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS, 29201.51Skamil "the status file in procfs"); 29211.1Skamil#endif 29221.1Skamil 29231.51Skamil/// ---------------------------------------------------------------------------- 29241.1Skamil 29251.53Skamilstatic void 29261.53Skamileventmask_preserved(int event) 29271.1Skamil{ 29281.1Skamil const int exitval = 5; 29291.1Skamil const int sigval = SIGSTOP; 29301.1Skamil pid_t child, wpid; 29311.1Skamil#if defined(TWAIT_HAVE_STATUS) 29321.1Skamil int status; 29331.1Skamil#endif 29341.1Skamil ptrace_event_t set_event, get_event; 29351.1Skamil const int len = sizeof(ptrace_event_t); 29361.1Skamil 29371.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 29381.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 29391.1Skamil if (child == 0) { 29401.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 29411.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 29421.1Skamil 29431.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 29441.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 29451.1Skamil 29461.13Schristos DPRINTF("Before exiting of the child process\n"); 29471.1Skamil _exit(exitval); 29481.1Skamil } 29491.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 29501.1Skamil 29511.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29521.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29531.1Skamil 29541.1Skamil validate_status_stopped(status, sigval); 29551.1Skamil 29561.53Skamil set_event.pe_set_event = event; 29571.61Skre SYSCALL_REQUIRE( 29581.61Skre ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); 29591.61Skre SYSCALL_REQUIRE( 29601.61Skre ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); 29611.125Skamil DPRINTF("set_event=%#x get_event=%#x\n", set_event.pe_set_event, 29621.125Skamil get_event.pe_set_event); 29631.1Skamil ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); 29641.1Skamil 29651.13Schristos DPRINTF("Before resuming the child process where it left off and " 29661.1Skamil "without signal to be sent\n"); 29671.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 29681.1Skamil 29691.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29701.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29711.1Skamil 29721.1Skamil validate_status_exited(status, exitval); 29731.1Skamil 29741.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29751.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 29761.1Skamil} 29771.1Skamil 29781.61Skre#define EVENTMASK_PRESERVED(test, event) \ 29791.61SkreATF_TC(test); \ 29801.61SkreATF_TC_HEAD(test, tc) \ 29811.61Skre{ \ 29821.61Skre atf_tc_set_md_var(tc, "descr", \ 29831.61Skre "Verify that eventmask " #event " is preserved"); \ 29841.61Skre} \ 29851.61Skre \ 29861.61SkreATF_TC_BODY(test, tc) \ 29871.61Skre{ \ 29881.61Skre \ 29891.61Skre eventmask_preserved(event); \ 29901.1Skamil} 29911.1Skamil 29921.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0) 29931.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK) 29941.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK) 29951.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE) 29961.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE) 29971.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT) 29981.125SkamilEVENTMASK_PRESERVED(eventmask_preserved_posix_spawn, PTRACE_POSIX_SPAWN) 29991.1Skamil 30001.53Skamil/// ---------------------------------------------------------------------------- 30011.1Skamil 30021.28Skamilstatic void 30031.125Skamilfork_body(const char *fn, bool trackspawn, bool trackfork, bool trackvfork, 30041.105Skamil bool trackvforkdone) 30051.1Skamil{ 30061.1Skamil const int exitval = 5; 30071.125Skamil const int exitval2 = 0; /* This matched exit status from /bin/echo */ 30081.1Skamil const int sigval = SIGSTOP; 30091.31Skamil pid_t child, child2 = 0, wpid; 30101.1Skamil#if defined(TWAIT_HAVE_STATUS) 30111.1Skamil int status; 30121.1Skamil#endif 30131.1Skamil ptrace_state_t state; 30141.1Skamil const int slen = sizeof(state); 30151.1Skamil ptrace_event_t event; 30161.1Skamil const int elen = sizeof(event); 30171.1Skamil 30181.124Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 30191.124Skamil 30201.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 30211.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 30221.1Skamil if (child == 0) { 30231.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 30241.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 30251.1Skamil 30261.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 30271.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 30281.1Skamil 30291.125Skamil if (strcmp(fn, "spawn") == 0) { 30301.124Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 30311.124Skamil arg[0], NULL, NULL, arg, NULL), 0); 30321.125Skamil } else { 30331.125Skamil if (strcmp(fn, "fork") == 0) { 30341.125Skamil FORKEE_ASSERT((child2 = fork()) != -1); 30351.125Skamil } else if (strcmp(fn, "vfork") == 0) { 30361.125Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 30371.125Skamil } 30381.1Skamil 30391.124Skamil if (child2 == 0) 30401.124Skamil _exit(exitval2); 30411.124Skamil } 30421.1Skamil FORKEE_REQUIRE_SUCCESS 30431.1Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 30441.1Skamil 30451.1Skamil forkee_status_exited(status, exitval2); 30461.1Skamil 30471.13Schristos DPRINTF("Before exiting of the child process\n"); 30481.1Skamil _exit(exitval); 30491.1Skamil } 30501.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 30511.1Skamil 30521.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 30531.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 30541.1Skamil 30551.1Skamil validate_status_stopped(status, sigval); 30561.1Skamil 30571.125Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 30581.125Skamil trackspawn ? "|PTRACE_POSIX_SPAWN" : "", 30591.61Skre trackfork ? "|PTRACE_FORK" : "", 30601.61Skre trackvfork ? "|PTRACE_VFORK" : "", 30611.61Skre trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 30621.30Skamil event.pe_set_event = 0; 30631.125Skamil if (trackspawn) 30641.125Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 30651.30Skamil if (trackfork) 30661.30Skamil event.pe_set_event |= PTRACE_FORK; 30671.30Skamil if (trackvfork) 30681.30Skamil event.pe_set_event |= PTRACE_VFORK; 30691.30Skamil if (trackvforkdone) 30701.30Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 30711.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 30721.1Skamil 30731.13Schristos DPRINTF("Before resuming the child process where it left off and " 30741.1Skamil "without signal to be sent\n"); 30751.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 30761.1Skamil 30771.29Skamil#if defined(TWAIT_HAVE_PID) 30781.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 30791.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 30801.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 30811.29Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 30821.61Skre child); 30831.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 30841.61Skre child); 30851.1Skamil 30861.29Skamil validate_status_stopped(status, SIGTRAP); 30871.1Skamil 30881.61Skre SYSCALL_REQUIRE( 30891.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 30901.125Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 30911.125Skamil ATF_REQUIRE_EQ( 30921.125Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 30931.125Skamil PTRACE_POSIX_SPAWN); 30941.125Skamil } 30951.125Skamil if (trackfork && strcmp(fn, "fork") == 0) { 30961.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 30971.30Skamil PTRACE_FORK); 30981.30Skamil } 30991.125Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 31001.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 31011.30Skamil PTRACE_VFORK); 31021.30Skamil } 31031.29Skamil 31041.29Skamil child2 = state.pe_other_pid; 31051.30Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 31061.29Skamil 31071.29Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 31081.61Skre "%d\n", TWAIT_FNAME, child2, child); 31091.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 31101.29Skamil child2); 31111.1Skamil 31121.29Skamil validate_status_stopped(status, SIGTRAP); 31131.1Skamil 31141.61Skre SYSCALL_REQUIRE( 31151.61Skre ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 31161.125Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 31171.125Skamil ATF_REQUIRE_EQ( 31181.125Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 31191.125Skamil PTRACE_POSIX_SPAWN); 31201.125Skamil } 31211.125Skamil if (trackfork && strcmp(fn, "fork") == 0) { 31221.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 31231.30Skamil PTRACE_FORK); 31241.30Skamil } 31251.125Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 31261.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 31271.30Skamil PTRACE_VFORK); 31281.30Skamil } 31291.30Skamil 31301.29Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 31311.29Skamil 31321.29Skamil DPRINTF("Before resuming the forkee process where it left off " 31331.29Skamil "and without signal to be sent\n"); 31341.61Skre SYSCALL_REQUIRE( 31351.61Skre ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 31361.29Skamil 31371.29Skamil DPRINTF("Before resuming the child process where it left off " 31381.61Skre "and without signal to be sent\n"); 31391.29Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31401.30Skamil } 31411.30Skamil#endif 31421.30Skamil 31431.125Skamil if (trackvforkdone && strcmp(fn, "vfork") == 0) { 31441.30Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 31451.61Skre child); 31461.61Skre TWAIT_REQUIRE_SUCCESS( 31471.61Skre wpid = TWAIT_GENERIC(child, &status, 0), child); 31481.30Skamil 31491.30Skamil validate_status_stopped(status, SIGTRAP); 31501.30Skamil 31511.61Skre SYSCALL_REQUIRE( 31521.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 31531.30Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 31541.30Skamil 31551.30Skamil child2 = state.pe_other_pid; 31561.30Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 31571.61Skre child2); 31581.30Skamil 31591.30Skamil DPRINTF("Before resuming the child process where it left off " 31601.61Skre "and without signal to be sent\n"); 31611.30Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31621.30Skamil } 31631.29Skamil 31641.30Skamil#if defined(TWAIT_HAVE_PID) 31651.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 31661.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 31671.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 31681.29Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 31691.61Skre "\n", TWAIT_FNAME); 31701.61Skre TWAIT_REQUIRE_SUCCESS( 31711.61Skre wpid = TWAIT_GENERIC(child2, &status, 0), child2); 31721.29Skamil 31731.29Skamil validate_status_exited(status, exitval2); 31741.29Skamil 31751.29Skamil DPRINTF("Before calling %s() for the forkee - expected no " 31761.61Skre "process\n", TWAIT_FNAME); 31771.29Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 31781.29Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 31791.29Skamil } 31801.29Skamil#endif 31811.1Skamil 31821.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 31831.1Skamil "SIGCHLD\n", TWAIT_FNAME); 31841.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31851.1Skamil 31861.1Skamil validate_status_stopped(status, SIGCHLD); 31871.1Skamil 31881.13Schristos DPRINTF("Before resuming the child process where it left off and " 31891.1Skamil "without signal to be sent\n"); 31901.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31911.1Skamil 31921.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 31931.1Skamil TWAIT_FNAME); 31941.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31951.1Skamil 31961.1Skamil validate_status_exited(status, exitval); 31971.1Skamil 31981.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 31991.1Skamil TWAIT_FNAME); 32001.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 32011.1Skamil} 32021.28Skamil 32031.125Skamil#define FORK_TEST(name,fun,tspawn,tfork,tvfork,tvforkdone) \ 32041.61SkreATF_TC(name); \ 32051.61SkreATF_TC_HEAD(name, tc) \ 32061.61Skre{ \ 32071.125Skamil atf_tc_set_md_var(tc, "descr", "Verify " fun "() " \ 32081.125Skamil "called with 0%s%s%s%s in EVENT_MASK", \ 32091.126Skamil tspawn ? "|PTRACE_POSIX_SPAWN" : "", \ 32101.105Skamil tfork ? "|PTRACE_FORK" : "", \ 32111.105Skamil tvfork ? "|PTRACE_VFORK" : "", \ 32121.105Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 32131.61Skre} \ 32141.61Skre \ 32151.61SkreATF_TC_BODY(name, tc) \ 32161.61Skre{ \ 32171.61Skre \ 32181.125Skamil fork_body(fun, tspawn, tfork, tvfork, tvforkdone); \ 32191.32Skamil} 32201.32Skamil 32211.125SkamilFORK_TEST(fork1, "fork", false, false, false, false) 32221.31Skamil#if defined(TWAIT_HAVE_PID) 32231.125SkamilFORK_TEST(fork2, "fork", false, true, false, false) 32241.125SkamilFORK_TEST(fork3, "fork", false, false, true, false) 32251.125SkamilFORK_TEST(fork4, "fork", false, true, true, false) 32261.31Skamil#endif 32271.125SkamilFORK_TEST(fork5, "fork", false, false, false, true) 32281.31Skamil#if defined(TWAIT_HAVE_PID) 32291.125SkamilFORK_TEST(fork6, "fork", false, true, false, true) 32301.125SkamilFORK_TEST(fork7, "fork", false, false, true, true) 32311.125SkamilFORK_TEST(fork8, "fork", false, true, true, true) 32321.125Skamil#endif 32331.125SkamilFORK_TEST(fork9, "fork", true, false, false, false) 32341.125Skamil#if defined(TWAIT_HAVE_PID) 32351.125SkamilFORK_TEST(fork10, "fork", true, true, false, false) 32361.125SkamilFORK_TEST(fork11, "fork", true, false, true, false) 32371.125SkamilFORK_TEST(fork12, "fork", true, true, true, false) 32381.125Skamil#endif 32391.125SkamilFORK_TEST(fork13, "fork", true, false, false, true) 32401.125Skamil#if defined(TWAIT_HAVE_PID) 32411.125SkamilFORK_TEST(fork14, "fork", true, true, false, true) 32421.125SkamilFORK_TEST(fork15, "fork", true, false, true, true) 32431.125SkamilFORK_TEST(fork16, "fork", true, true, true, true) 32441.31Skamil#endif 32451.1Skamil 32461.110Skamil#if TEST_VFORK_ENABLED 32471.125SkamilFORK_TEST(vfork1, "vfork", false, false, false, false) 32481.31Skamil#if defined(TWAIT_HAVE_PID) 32491.125SkamilFORK_TEST(vfork2, "vfork", false, true, false, false) 32501.125SkamilFORK_TEST(vfork3, "vfork", false, false, true, false) 32511.125SkamilFORK_TEST(vfork4, "vfork", false, true, true, false) 32521.31Skamil#endif 32531.125SkamilFORK_TEST(vfork5, "vfork", false, false, false, true) 32541.31Skamil#if defined(TWAIT_HAVE_PID) 32551.125SkamilFORK_TEST(vfork6, "vfork", false, true, false, true) 32561.125SkamilFORK_TEST(vfork7, "vfork", false, false, true, true) 32571.125SkamilFORK_TEST(vfork8, "vfork", false, true, true, true) 32581.31Skamil#endif 32591.125SkamilFORK_TEST(vfork9, "vfork", true, false, false, false) 32601.125Skamil#if defined(TWAIT_HAVE_PID) 32611.125SkamilFORK_TEST(vfork10, "vfork", true, true, false, false) 32621.125SkamilFORK_TEST(vfork11, "vfork", true, false, true, false) 32631.125SkamilFORK_TEST(vfork12, "vfork", true, true, true, false) 32641.110Skamil#endif 32651.125SkamilFORK_TEST(vfork13, "vfork", true, false, false, true) 32661.124Skamil#if defined(TWAIT_HAVE_PID) 32671.125SkamilFORK_TEST(vfork14, "vfork", true, true, false, true) 32681.125SkamilFORK_TEST(vfork15, "vfork", true, false, true, true) 32691.125SkamilFORK_TEST(vfork16, "vfork", true, true, true, true) 32701.124Skamil#endif 32711.125Skamil#endif 32721.125Skamil 32731.125SkamilFORK_TEST(posix_spawn1, "spawn", false, false, false, false) 32741.125SkamilFORK_TEST(posix_spawn2, "spawn", false, true, false, false) 32751.125SkamilFORK_TEST(posix_spawn3, "spawn", false, false, true, false) 32761.125SkamilFORK_TEST(posix_spawn4, "spawn", false, true, true, false) 32771.125SkamilFORK_TEST(posix_spawn5, "spawn", false, false, false, true) 32781.125SkamilFORK_TEST(posix_spawn6, "spawn", false, true, false, true) 32791.125SkamilFORK_TEST(posix_spawn7, "spawn", false, false, true, true) 32801.125SkamilFORK_TEST(posix_spawn8, "spawn", false, true, true, true) 32811.124Skamil#if defined(TWAIT_HAVE_PID) 32821.125SkamilFORK_TEST(posix_spawn9, "spawn", true, false, false, false) 32831.125SkamilFORK_TEST(posix_spawn10, "spawn", true, true, false, false) 32841.125SkamilFORK_TEST(posix_spawn11, "spawn", true, false, true, false) 32851.125SkamilFORK_TEST(posix_spawn12, "spawn", true, true, true, false) 32861.125SkamilFORK_TEST(posix_spawn13, "spawn", true, false, false, true) 32871.125SkamilFORK_TEST(posix_spawn14, "spawn", true, true, false, true) 32881.125SkamilFORK_TEST(posix_spawn15, "spawn", true, false, true, true) 32891.125SkamilFORK_TEST(posix_spawn16, "spawn", true, true, true, true) 32901.124Skamil#endif 32911.124Skamil 32921.54Skamil/// ---------------------------------------------------------------------------- 32931.31Skamil 32941.116Skamil#if defined(TWAIT_HAVE_PID) 32951.116Skamilstatic void 32961.126Skamilfork_detach_forker_body(const char *fn, bool kill_process) 32971.116Skamil{ 32981.116Skamil const int exitval = 5; 32991.126Skamil const int exitval2 = 0; /* Matches exit value from /bin/echo */ 33001.116Skamil const int sigval = SIGSTOP; 33011.116Skamil pid_t child, child2 = 0, wpid; 33021.116Skamil#if defined(TWAIT_HAVE_STATUS) 33031.116Skamil int status; 33041.116Skamil#endif 33051.116Skamil ptrace_state_t state; 33061.116Skamil const int slen = sizeof(state); 33071.116Skamil ptrace_event_t event; 33081.116Skamil const int elen = sizeof(event); 33091.116Skamil 33101.116Skamil int op; 33111.116Skamil 33121.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 33131.116Skamil 33141.116Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 33151.116Skamil SYSCALL_REQUIRE((child = fork()) != -1); 33161.116Skamil if (child == 0) { 33171.116Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 33181.116Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 33191.116Skamil 33201.116Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 33211.116Skamil FORKEE_ASSERT(raise(sigval) == 0); 33221.116Skamil 33231.126Skamil if (strcmp(fn, "spawn") == 0) { 33241.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 33251.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 33261.126Skamil } else { 33271.126Skamil if (strcmp(fn, "fork") == 0) { 33281.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 33291.126Skamil } else { 33301.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 33311.126Skamil } 33321.116Skamil 33331.126Skamil if (child2 == 0) 33341.126Skamil _exit(exitval2); 33351.126Skamil } 33361.116Skamil 33371.116Skamil FORKEE_REQUIRE_SUCCESS 33381.116Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 33391.116Skamil 33401.116Skamil forkee_status_exited(status, exitval2); 33411.116Skamil 33421.116Skamil DPRINTF("Before exiting of the child process\n"); 33431.116Skamil _exit(exitval); 33441.116Skamil } 33451.116Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 33461.116Skamil 33471.116Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 33481.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33491.116Skamil 33501.116Skamil validate_status_stopped(status, sigval); 33511.116Skamil 33521.116Skamil DPRINTF("Set EVENT_MASK for the child %d\n", child); 33531.126Skamil event.pe_set_event = PTRACE_POSIX_SPAWN | PTRACE_FORK | PTRACE_VFORK 33541.126Skamil | PTRACE_VFORK_DONE; 33551.116Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 33561.116Skamil 33571.116Skamil DPRINTF("Before resuming the child process where it left off and " 33581.116Skamil "without signal to be sent\n"); 33591.116Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 33601.116Skamil 33611.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child); 33621.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33631.116Skamil 33641.116Skamil validate_status_stopped(status, SIGTRAP); 33651.116Skamil 33661.116Skamil SYSCALL_REQUIRE( 33671.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 33681.126Skamil 33691.126Skamil if (strcmp(fn, "spawn") == 0) 33701.126Skamil op = PTRACE_POSIX_SPAWN; 33711.126Skamil else if (strcmp(fn, "fork") == 0) 33721.126Skamil op = PTRACE_FORK; 33731.126Skamil else 33741.126Skamil op = PTRACE_VFORK; 33751.126Skamil 33761.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 33771.116Skamil 33781.116Skamil child2 = state.pe_other_pid; 33791.116Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 33801.116Skamil 33811.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 33821.126Skamil strcmp(fn, "vfork") == 0) 33831.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 33841.116Skamil else 33851.116Skamil op = PT_CONTINUE; 33861.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 33871.116Skamil 33881.116Skamil DPRINTF("Before calling %s() for the forkee %d of the child %d\n", 33891.116Skamil TWAIT_FNAME, child2, child); 33901.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 33911.116Skamil 33921.116Skamil validate_status_stopped(status, SIGTRAP); 33931.116Skamil 33941.116Skamil SYSCALL_REQUIRE( 33951.116Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 33961.126Skamil if (strcmp(fn, "spawn") == 0) 33971.126Skamil op = PTRACE_POSIX_SPAWN; 33981.126Skamil else if (strcmp(fn, "fork") == 0) 33991.126Skamil op = PTRACE_FORK; 34001.126Skamil else 34011.126Skamil op = PTRACE_VFORK; 34021.126Skamil 34031.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 34041.116Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 34051.116Skamil 34061.116Skamil DPRINTF("Before resuming the forkee process where it left off " 34071.116Skamil "and without signal to be sent\n"); 34081.116Skamil SYSCALL_REQUIRE( 34091.116Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 34101.116Skamil 34111.126Skamil if (strcmp(fn, "vforkdone") == 0) { 34121.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 34131.116Skamil child); 34141.116Skamil TWAIT_REQUIRE_SUCCESS( 34151.116Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 34161.116Skamil 34171.116Skamil validate_status_stopped(status, SIGTRAP); 34181.116Skamil 34191.116Skamil SYSCALL_REQUIRE( 34201.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 34211.116Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 34221.116Skamil 34231.116Skamil child2 = state.pe_other_pid; 34241.116Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 34251.116Skamil child2); 34261.116Skamil 34271.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 34281.116Skamil DPRINTF("Before resuming the child process where it left off " 34291.116Skamil "and without signal to be sent\n"); 34301.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 34311.116Skamil } 34321.116Skamil 34331.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 34341.116Skamil TWAIT_FNAME); 34351.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 34361.116Skamil 34371.116Skamil validate_status_exited(status, exitval2); 34381.116Skamil 34391.116Skamil DPRINTF("Before calling %s() for the forkee - expected no process\n", 34401.116Skamil TWAIT_FNAME); 34411.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child2, &status, 0)); 34421.116Skamil 34431.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 34441.116Skamil TWAIT_FNAME); 34451.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 34461.116Skamil 34471.116Skamil if (kill_process) { 34481.116Skamil validate_status_signaled(status, SIGKILL, 0); 34491.116Skamil } else { 34501.116Skamil validate_status_exited(status, exitval); 34511.116Skamil } 34521.116Skamil 34531.116Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 34541.116Skamil TWAIT_FNAME); 34551.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 34561.116Skamil} 34571.116Skamil 34581.126Skamil#define FORK_DETACH_FORKER(name,event,kprocess) \ 34591.116SkamilATF_TC(name); \ 34601.116SkamilATF_TC_HEAD(name, tc) \ 34611.116Skamil{ \ 34621.126Skamil atf_tc_set_md_var(tc, "descr", "Verify %s " event, \ 34631.126Skamil kprocess ? "killed" : "detached"); \ 34641.116Skamil} \ 34651.116Skamil \ 34661.116SkamilATF_TC_BODY(name, tc) \ 34671.116Skamil{ \ 34681.116Skamil \ 34691.126Skamil fork_detach_forker_body(event, kprocess); \ 34701.116Skamil} 34711.116Skamil 34721.126SkamilFORK_DETACH_FORKER(posix_spawn_detach_spawner, "spawn", false) 34731.126SkamilFORK_DETACH_FORKER(fork_detach_forker, "fork", false) 34741.116Skamil#if TEST_VFORK_ENABLED 34751.126SkamilFORK_DETACH_FORKER(vfork_detach_vforker, "vfork", false) 34761.126SkamilFORK_DETACH_FORKER(vfork_detach_vforkerdone, "vforkdone", false) 34771.116Skamil#endif 34781.126Skamil 34791.126SkamilFORK_DETACH_FORKER(posix_spawn_kill_spawner, "spawn", true) 34801.126SkamilFORK_DETACH_FORKER(fork_kill_forker, "fork", true) 34811.116Skamil#if TEST_VFORK_ENABLED 34821.126SkamilFORK_DETACH_FORKER(vfork_kill_vforker, "vfork", true) 34831.126SkamilFORK_DETACH_FORKER(vfork_kill_vforkerdone, "vforkdone", true) 34841.116Skamil#endif 34851.116Skamil#endif 34861.116Skamil 34871.116Skamil/// ---------------------------------------------------------------------------- 34881.116Skamil 34891.110Skamil#if TEST_VFORK_ENABLED 34901.108Skamilstatic void 34911.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void)) 34921.108Skamil{ 34931.108Skamil const int exitval = 5; 34941.108Skamil const int exitval2 = 15; 34951.108Skamil pid_t child, child2 = 0, wpid; 34961.108Skamil#if defined(TWAIT_HAVE_STATUS) 34971.108Skamil int status; 34981.108Skamil#endif 34991.108Skamil 35001.108Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 35011.108Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 35021.108Skamil if (child == 0) { 35031.108Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 35041.108Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 35051.108Skamil 35061.108Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 35071.108Skamil 35081.108Skamil if (child2 == 0) 35091.108Skamil _exit(exitval2); 35101.108Skamil 35111.108Skamil FORKEE_REQUIRE_SUCCESS 35121.108Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 35131.108Skamil 35141.108Skamil forkee_status_exited(status, exitval2); 35151.108Skamil 35161.108Skamil DPRINTF("Before exiting of the child process\n"); 35171.108Skamil _exit(exitval); 35181.108Skamil } 35191.108Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 35201.108Skamil 35211.108Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 35221.108Skamil TWAIT_FNAME); 35231.108Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 35241.108Skamil 35251.108Skamil validate_status_exited(status, exitval); 35261.108Skamil 35271.108Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 35281.108Skamil TWAIT_FNAME); 35291.108Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 35301.108Skamil} 35311.108Skamil 35321.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun) \ 35331.108SkamilATF_TC(name); \ 35341.108SkamilATF_TC_HEAD(name, tc) \ 35351.108Skamil{ \ 35361.108Skamil atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) " \ 35371.108Skamil "called from vfork(2)ed child"); \ 35381.108Skamil} \ 35391.108Skamil \ 35401.108SkamilATF_TC_BODY(name, tc) \ 35411.108Skamil{ \ 35421.108Skamil \ 35431.108Skamil traceme_vfork_fork_body(fun); \ 35441.108Skamil} 35451.108Skamil 35461.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork) 35471.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork) 35481.110Skamil#endif 35491.108Skamil 35501.108Skamil/// ---------------------------------------------------------------------------- 35511.108Skamil 35521.54Skamilenum bytes_transfer_type { 35531.54Skamil BYTES_TRANSFER_DATA, 35541.54Skamil BYTES_TRANSFER_DATAIO, 35551.54Skamil BYTES_TRANSFER_TEXT, 35561.54Skamil BYTES_TRANSFER_TEXTIO, 35571.54Skamil BYTES_TRANSFER_AUXV 35581.54Skamil}; 35591.31Skamil 35601.54Skamilstatic int __used 35611.54Skamilbytes_transfer_dummy(int a, int b, int c, int d) 35621.54Skamil{ 35631.54Skamil int e, f, g, h; 35641.1Skamil 35651.54Skamil a *= 4; 35661.54Skamil b += 3; 35671.54Skamil c -= 2; 35681.54Skamil d /= 1; 35691.1Skamil 35701.54Skamil e = strtol("10", NULL, 10); 35711.54Skamil f = strtol("20", NULL, 10); 35721.54Skamil g = strtol("30", NULL, 10); 35731.54Skamil h = strtol("40", NULL, 10); 35741.1Skamil 35751.54Skamil return (a + b * c - d) + (e * f - g / h); 35761.1Skamil} 35771.1Skamil 35781.54Skamilstatic void 35791.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type) 35801.1Skamil{ 35811.1Skamil const int exitval = 5; 35821.1Skamil const int sigval = SIGSTOP; 35831.1Skamil pid_t child, wpid; 35841.54Skamil bool skip = false; 35851.1Skamil 35861.54Skamil int lookup_me = 0; 35871.54Skamil uint8_t lookup_me8 = 0; 35881.54Skamil uint16_t lookup_me16 = 0; 35891.54Skamil uint32_t lookup_me32 = 0; 35901.54Skamil uint64_t lookup_me64 = 0; 35911.1Skamil 35921.54Skamil int magic = 0x13579246; 35931.54Skamil uint8_t magic8 = 0xab; 35941.54Skamil uint16_t magic16 = 0x1234; 35951.54Skamil uint32_t magic32 = 0x98765432; 35961.54Skamil uint64_t magic64 = 0xabcdef0123456789; 35971.1Skamil 35981.54Skamil struct ptrace_io_desc io; 35991.1Skamil#if defined(TWAIT_HAVE_STATUS) 36001.1Skamil int status; 36011.1Skamil#endif 36021.60Skre /* 513 is just enough, for the purposes of ATF it's good enough */ 36031.60Skre AuxInfo ai[513], *aip; 36041.55Schristos 36051.55Schristos ATF_REQUIRE(size < sizeof(ai)); 36061.1Skamil 36071.54Skamil /* Prepare variables for .TEXT transfers */ 36081.54Skamil switch (type) { 36091.54Skamil case BYTES_TRANSFER_TEXT: 36101.54Skamil memcpy(&magic, bytes_transfer_dummy, sizeof(magic)); 36111.54Skamil break; 36121.54Skamil case BYTES_TRANSFER_TEXTIO: 36131.54Skamil switch (size) { 36141.54Skamil case 8: 36151.54Skamil memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8)); 36161.54Skamil break; 36171.54Skamil case 16: 36181.54Skamil memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16)); 36191.54Skamil break; 36201.54Skamil case 32: 36211.54Skamil memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32)); 36221.54Skamil break; 36231.54Skamil case 64: 36241.54Skamil memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64)); 36251.54Skamil break; 36261.54Skamil } 36271.54Skamil break; 36281.54Skamil default: 36291.54Skamil break; 36301.54Skamil } 36311.1Skamil 36321.54Skamil /* Prepare variables for PIOD and AUXV transfers */ 36331.54Skamil switch (type) { 36341.54Skamil case BYTES_TRANSFER_TEXTIO: 36351.54Skamil case BYTES_TRANSFER_DATAIO: 36361.54Skamil io.piod_op = operation; 36371.54Skamil switch (size) { 36381.54Skamil case 8: 36391.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36401.54Skamil (void *)bytes_transfer_dummy : 36411.54Skamil &lookup_me8; 36421.54Skamil io.piod_addr = &lookup_me8; 36431.54Skamil io.piod_len = sizeof(lookup_me8); 36441.54Skamil break; 36451.54Skamil case 16: 36461.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36471.54Skamil (void *)bytes_transfer_dummy : 36481.54Skamil &lookup_me16; 36491.54Skamil io.piod_addr = &lookup_me16; 36501.54Skamil io.piod_len = sizeof(lookup_me16); 36511.54Skamil break; 36521.54Skamil case 32: 36531.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36541.54Skamil (void *)bytes_transfer_dummy : 36551.54Skamil &lookup_me32; 36561.54Skamil io.piod_addr = &lookup_me32; 36571.54Skamil io.piod_len = sizeof(lookup_me32); 36581.54Skamil break; 36591.54Skamil case 64: 36601.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36611.54Skamil (void *)bytes_transfer_dummy : 36621.54Skamil &lookup_me64; 36631.54Skamil io.piod_addr = &lookup_me64; 36641.54Skamil io.piod_len = sizeof(lookup_me64); 36651.54Skamil break; 36661.54Skamil default: 36671.54Skamil break; 36681.54Skamil } 36691.54Skamil break; 36701.54Skamil case BYTES_TRANSFER_AUXV: 36711.54Skamil io.piod_op = operation; 36721.54Skamil io.piod_offs = 0; 36731.54Skamil io.piod_addr = ai; 36741.54Skamil io.piod_len = size; 36751.54Skamil break; 36761.54Skamil default: 36771.54Skamil break; 36781.1Skamil } 36791.1Skamil 36801.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 36811.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 36821.1Skamil if (child == 0) { 36831.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 36841.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 36851.1Skamil 36861.54Skamil switch (type) { 36871.54Skamil case BYTES_TRANSFER_DATA: 36881.54Skamil switch (operation) { 36891.54Skamil case PT_READ_D: 36901.54Skamil case PT_READ_I: 36911.54Skamil lookup_me = magic; 36921.54Skamil break; 36931.54Skamil default: 36941.54Skamil break; 36951.54Skamil } 36961.54Skamil break; 36971.54Skamil case BYTES_TRANSFER_DATAIO: 36981.54Skamil switch (operation) { 36991.54Skamil case PIOD_READ_D: 37001.54Skamil case PIOD_READ_I: 37011.54Skamil switch (size) { 37021.54Skamil case 8: 37031.54Skamil lookup_me8 = magic8; 37041.54Skamil break; 37051.54Skamil case 16: 37061.54Skamil lookup_me16 = magic16; 37071.54Skamil break; 37081.54Skamil case 32: 37091.54Skamil lookup_me32 = magic32; 37101.54Skamil break; 37111.54Skamil case 64: 37121.54Skamil lookup_me64 = magic64; 37131.54Skamil break; 37141.54Skamil default: 37151.54Skamil break; 37161.54Skamil } 37171.54Skamil break; 37181.54Skamil default: 37191.54Skamil break; 37201.54Skamil } 37211.54Skamil default: 37221.54Skamil break; 37231.54Skamil } 37241.54Skamil 37251.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 37261.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 37271.1Skamil 37281.54Skamil /* Handle PIOD and PT separately as operation values overlap */ 37291.54Skamil switch (type) { 37301.54Skamil case BYTES_TRANSFER_DATA: 37311.54Skamil switch (operation) { 37321.54Skamil case PT_WRITE_D: 37331.54Skamil case PT_WRITE_I: 37341.54Skamil FORKEE_ASSERT_EQ(lookup_me, magic); 37351.54Skamil break; 37361.54Skamil default: 37371.54Skamil break; 37381.54Skamil } 37391.54Skamil break; 37401.54Skamil case BYTES_TRANSFER_DATAIO: 37411.54Skamil switch (operation) { 37421.54Skamil case PIOD_WRITE_D: 37431.54Skamil case PIOD_WRITE_I: 37441.54Skamil switch (size) { 37451.54Skamil case 8: 37461.54Skamil FORKEE_ASSERT_EQ(lookup_me8, magic8); 37471.54Skamil break; 37481.54Skamil case 16: 37491.54Skamil FORKEE_ASSERT_EQ(lookup_me16, magic16); 37501.54Skamil break; 37511.54Skamil case 32: 37521.54Skamil FORKEE_ASSERT_EQ(lookup_me32, magic32); 37531.54Skamil break; 37541.54Skamil case 64: 37551.54Skamil FORKEE_ASSERT_EQ(lookup_me64, magic64); 37561.54Skamil break; 37571.54Skamil default: 37581.54Skamil break; 37591.54Skamil } 37601.54Skamil break; 37611.54Skamil default: 37621.54Skamil break; 37631.54Skamil } 37641.54Skamil break; 37651.54Skamil case BYTES_TRANSFER_TEXT: 37661.54Skamil FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy, 37671.54Skamil sizeof(magic)) == 0); 37681.54Skamil break; 37691.54Skamil case BYTES_TRANSFER_TEXTIO: 37701.54Skamil switch (size) { 37711.54Skamil case 8: 37721.54Skamil FORKEE_ASSERT(memcmp(&magic8, 37731.54Skamil bytes_transfer_dummy, 37741.54Skamil sizeof(magic8)) == 0); 37751.54Skamil break; 37761.54Skamil case 16: 37771.54Skamil FORKEE_ASSERT(memcmp(&magic16, 37781.54Skamil bytes_transfer_dummy, 37791.54Skamil sizeof(magic16)) == 0); 37801.54Skamil break; 37811.54Skamil case 32: 37821.54Skamil FORKEE_ASSERT(memcmp(&magic32, 37831.54Skamil bytes_transfer_dummy, 37841.54Skamil sizeof(magic32)) == 0); 37851.54Skamil break; 37861.54Skamil case 64: 37871.54Skamil FORKEE_ASSERT(memcmp(&magic64, 37881.54Skamil bytes_transfer_dummy, 37891.54Skamil sizeof(magic64)) == 0); 37901.54Skamil break; 37911.54Skamil } 37921.54Skamil break; 37931.54Skamil default: 37941.54Skamil break; 37951.54Skamil } 37961.54Skamil 37971.13Schristos DPRINTF("Before exiting of the child process\n"); 37981.1Skamil _exit(exitval); 37991.1Skamil } 38001.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 38011.1Skamil 38021.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38031.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 38041.1Skamil 38051.1Skamil validate_status_stopped(status, sigval); 38061.1Skamil 38071.54Skamil /* Check PaX MPROTECT */ 38081.54Skamil if (!can_we_write_to_text(child)) { 38091.54Skamil switch (type) { 38101.54Skamil case BYTES_TRANSFER_TEXTIO: 38111.54Skamil switch (operation) { 38121.54Skamil case PIOD_WRITE_D: 38131.54Skamil case PIOD_WRITE_I: 38141.54Skamil skip = true; 38151.54Skamil break; 38161.54Skamil default: 38171.54Skamil break; 38181.54Skamil } 38191.54Skamil break; 38201.54Skamil case BYTES_TRANSFER_TEXT: 38211.54Skamil switch (operation) { 38221.54Skamil case PT_WRITE_D: 38231.54Skamil case PT_WRITE_I: 38241.54Skamil skip = true; 38251.54Skamil break; 38261.54Skamil default: 38271.54Skamil break; 38281.54Skamil } 38291.54Skamil break; 38301.54Skamil default: 38311.54Skamil break; 38321.54Skamil } 38331.54Skamil } 38341.1Skamil 38351.54Skamil /* Bailout cleanly killing the child process */ 38361.54Skamil if (skip) { 38371.54Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1); 38381.54Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38391.54Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 38401.54Skamil child); 38411.1Skamil 38421.54Skamil validate_status_signaled(status, SIGKILL, 0); 38431.1Skamil 38441.54Skamil atf_tc_skip("PaX MPROTECT setup prevents writes to .text"); 38451.54Skamil } 38461.1Skamil 38471.54Skamil DPRINTF("Calling operation to transfer bytes between child=%d and " 38481.54Skamil "parent=%d\n", child, getpid()); 38491.1Skamil 38501.54Skamil switch (type) { 38511.54Skamil case BYTES_TRANSFER_TEXTIO: 38521.54Skamil case BYTES_TRANSFER_DATAIO: 38531.54Skamil case BYTES_TRANSFER_AUXV: 38541.54Skamil switch (operation) { 38551.54Skamil case PIOD_WRITE_D: 38561.54Skamil case PIOD_WRITE_I: 38571.54Skamil switch (size) { 38581.54Skamil case 8: 38591.54Skamil lookup_me8 = magic8; 38601.54Skamil break; 38611.54Skamil case 16: 38621.54Skamil lookup_me16 = magic16; 38631.54Skamil break; 38641.54Skamil case 32: 38651.54Skamil lookup_me32 = magic32; 38661.54Skamil break; 38671.54Skamil case 64: 38681.54Skamil lookup_me64 = magic64; 38691.54Skamil break; 38701.54Skamil default: 38711.54Skamil break; 38721.54Skamil } 38731.54Skamil break; 38741.54Skamil default: 38751.54Skamil break; 38761.54Skamil } 38771.54Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); 38781.54Skamil switch (operation) { 38791.54Skamil case PIOD_READ_D: 38801.54Skamil case PIOD_READ_I: 38811.54Skamil switch (size) { 38821.54Skamil case 8: 38831.54Skamil ATF_REQUIRE_EQ(lookup_me8, magic8); 38841.54Skamil break; 38851.54Skamil case 16: 38861.54Skamil ATF_REQUIRE_EQ(lookup_me16, magic16); 38871.54Skamil break; 38881.54Skamil case 32: 38891.54Skamil ATF_REQUIRE_EQ(lookup_me32, magic32); 38901.54Skamil break; 38911.54Skamil case 64: 38921.54Skamil ATF_REQUIRE_EQ(lookup_me64, magic64); 38931.54Skamil break; 38941.54Skamil default: 38951.54Skamil break; 38961.54Skamil } 38971.54Skamil break; 38981.54Skamil case PIOD_READ_AUXV: 38991.54Skamil DPRINTF("Asserting that AUXV length (%zu) is > 0\n", 39001.54Skamil io.piod_len); 39011.54Skamil ATF_REQUIRE(io.piod_len > 0); 39021.54Skamil for (aip = ai; aip->a_type != AT_NULL; aip++) 39031.54Skamil DPRINTF("a_type=%#llx a_v=%#llx\n", 39041.54Skamil (long long int)aip->a_type, 39051.54Skamil (long long int)aip->a_v); 39061.54Skamil break; 39071.54Skamil default: 39081.54Skamil break; 39091.54Skamil } 39101.54Skamil break; 39111.54Skamil case BYTES_TRANSFER_TEXT: 39121.54Skamil switch (operation) { 39131.54Skamil case PT_READ_D: 39141.54Skamil case PT_READ_I: 39151.54Skamil errno = 0; 39161.54Skamil lookup_me = ptrace(operation, child, 39171.54Skamil bytes_transfer_dummy, 0); 39181.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 39191.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 39201.54Skamil break; 39211.54Skamil case PT_WRITE_D: 39221.54Skamil case PT_WRITE_I: 39231.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, 39241.54Skamil bytes_transfer_dummy, magic) 39251.54Skamil != -1); 39261.54Skamil break; 39271.54Skamil default: 39281.54Skamil break; 39291.54Skamil } 39301.54Skamil break; 39311.54Skamil case BYTES_TRANSFER_DATA: 39321.54Skamil switch (operation) { 39331.54Skamil case PT_READ_D: 39341.54Skamil case PT_READ_I: 39351.54Skamil errno = 0; 39361.54Skamil lookup_me = ptrace(operation, child, &lookup_me, 0); 39371.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 39381.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 39391.54Skamil break; 39401.54Skamil case PT_WRITE_D: 39411.54Skamil case PT_WRITE_I: 39421.54Skamil lookup_me = magic; 39431.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me, 39441.54Skamil magic) != -1); 39451.54Skamil break; 39461.54Skamil default: 39471.54Skamil break; 39481.54Skamil } 39491.54Skamil break; 39501.54Skamil default: 39511.54Skamil break; 39521.54Skamil } 39531.1Skamil 39541.13Schristos DPRINTF("Before resuming the child process where it left off and " 39551.1Skamil "without signal to be sent\n"); 39561.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 39571.1Skamil 39581.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39591.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 39601.1Skamil 39611.1Skamil validate_status_exited(status, exitval); 39621.1Skamil 39631.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39641.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 39651.1Skamil} 39661.1Skamil 39671.61Skre#define BYTES_TRANSFER(test, operation, size, type) \ 39681.61SkreATF_TC(test); \ 39691.61SkreATF_TC_HEAD(test, tc) \ 39701.61Skre{ \ 39711.61Skre atf_tc_set_md_var(tc, "descr", \ 39721.61Skre "Verify bytes transfer operation" #operation " and size " #size \ 39731.61Skre " of type " #type); \ 39741.61Skre} \ 39751.61Skre \ 39761.61SkreATF_TC_BODY(test, tc) \ 39771.61Skre{ \ 39781.61Skre \ 39791.61Skre bytes_transfer(operation, size, BYTES_TRANSFER_##type); \ 39801.1Skamil} 39811.1Skamil 39821.54Skamil// DATA 39831.1Skamil 39841.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO) 39851.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO) 39861.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO) 39871.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO) 39881.54Skamil 39891.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO) 39901.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO) 39911.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO) 39921.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO) 39931.54Skamil 39941.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO) 39951.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO) 39961.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO) 39971.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO) 39981.54Skamil 39991.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO) 40001.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO) 40011.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO) 40021.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO) 40031.54Skamil 40041.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA) 40051.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA) 40061.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA) 40071.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA) 40081.54Skamil 40091.54Skamil// TEXT 40101.54Skamil 40111.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO) 40121.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO) 40131.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO) 40141.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO) 40151.54Skamil 40161.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO) 40171.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO) 40181.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO) 40191.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO) 40201.54Skamil 40211.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO) 40221.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO) 40231.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO) 40241.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO) 40251.54Skamil 40261.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO) 40271.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO) 40281.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO) 40291.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO) 40301.54Skamil 40311.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT) 40321.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT) 40331.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT) 40341.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT) 40351.1Skamil 40361.54Skamil// AUXV 40371.1Skamil 40381.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV) 40391.1Skamil 40401.54Skamil/// ---------------------------------------------------------------------------- 40411.1Skamil 40421.101Skamilstatic void 40431.101Skamilbytes_transfer_alignment(const char *operation) 40441.101Skamil{ 40451.101Skamil const int exitval = 5; 40461.101Skamil const int sigval = SIGSTOP; 40471.101Skamil pid_t child, wpid; 40481.101Skamil#if defined(TWAIT_HAVE_STATUS) 40491.101Skamil int status; 40501.101Skamil#endif 40511.101Skamil char *buffer; 40521.101Skamil int vector; 40531.101Skamil size_t len; 40541.101Skamil size_t i; 40551.101Skamil int op; 40561.101Skamil 40571.101Skamil struct ptrace_io_desc io; 40581.101Skamil struct ptrace_siginfo info; 40591.101Skamil 40601.101Skamil memset(&io, 0, sizeof(io)); 40611.101Skamil memset(&info, 0, sizeof(info)); 40621.101Skamil 40631.101Skamil /* Testing misaligned byte transfer crossing page boundaries */ 40641.101Skamil len = sysconf(_SC_PAGESIZE) * 2; 40651.101Skamil buffer = malloc(len); 40661.101Skamil ATF_REQUIRE(buffer != NULL); 40671.101Skamil 40681.101Skamil /* Initialize the buffer with random data */ 40691.101Skamil for (i = 0; i < len; i++) 40701.101Skamil buffer[i] = i & 0xff; 40711.101Skamil 40721.101Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 40731.101Skamil SYSCALL_REQUIRE((child = fork()) != -1); 40741.101Skamil if (child == 0) { 40751.101Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 40761.101Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 40771.101Skamil 40781.101Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 40791.101Skamil FORKEE_ASSERT(raise(sigval) == 0); 40801.101Skamil 40811.101Skamil DPRINTF("Before exiting of the child process\n"); 40821.101Skamil _exit(exitval); 40831.101Skamil } 40841.101Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 40851.101Skamil 40861.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 40871.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 40881.101Skamil 40891.101Skamil validate_status_stopped(status, sigval); 40901.101Skamil 40911.101Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 40921.101Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 40931.101Skamil != -1); 40941.101Skamil 40951.101Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 40961.101Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 40971.101Skamil "si_errno=%#x\n", 40981.101Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 40991.101Skamil info.psi_siginfo.si_errno); 41001.101Skamil 41011.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 41021.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 41031.101Skamil 41041.101Skamil if (strcmp(operation, "PT_READ_I") == 0 || 41051.101Skamil strcmp(operation, "PT_READ_D") == 0) { 41061.101Skamil if (strcmp(operation, "PT_READ_I")) 41071.101Skamil op = PT_READ_I; 41081.101Skamil else 41091.101Skamil op = PT_READ_D; 41101.101Skamil 41111.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41121.101Skamil errno = 0; 41131.101Skamil vector = ptrace(op, child, buffer + i, 0); 41141.101Skamil ATF_REQUIRE_EQ(errno, 0); 41151.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 41161.101Skamil } 41171.101Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 41181.101Skamil strcmp(operation, "PT_WRITE_D") == 0) { 41191.101Skamil if (strcmp(operation, "PT_WRITE_I")) 41201.101Skamil op = PT_WRITE_I; 41211.101Skamil else 41221.101Skamil op = PT_WRITE_D; 41231.101Skamil 41241.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41251.101Skamil memcpy(&vector, buffer + i, sizeof(int)); 41261.101Skamil SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector) 41271.101Skamil != -1); 41281.101Skamil } 41291.101Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 41301.101Skamil strcmp(operation, "PIOD_READ_D") == 0) { 41311.101Skamil if (strcmp(operation, "PIOD_READ_I")) 41321.101Skamil op = PIOD_READ_I; 41331.101Skamil else 41341.101Skamil op = PIOD_READ_D; 41351.101Skamil 41361.101Skamil io.piod_op = op; 41371.101Skamil io.piod_addr = &vector; 41381.101Skamil io.piod_len = sizeof(int); 41391.101Skamil 41401.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41411.101Skamil io.piod_offs = buffer + i; 41421.101Skamil 41431.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41441.101Skamil != -1); 41451.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 41461.101Skamil } 41471.101Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 41481.101Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 41491.101Skamil if (strcmp(operation, "PIOD_WRITE_I")) 41501.101Skamil op = PIOD_WRITE_I; 41511.101Skamil else 41521.101Skamil op = PIOD_WRITE_D; 41531.101Skamil 41541.101Skamil io.piod_op = op; 41551.101Skamil io.piod_addr = &vector; 41561.101Skamil io.piod_len = sizeof(int); 41571.101Skamil 41581.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41591.101Skamil io.piod_offs = buffer + i; 41601.101Skamil 41611.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41621.101Skamil != -1); 41631.101Skamil } 41641.101Skamil } else if (strcmp(operation, "PIOD_READ_AUXV") == 0) { 41651.101Skamil io.piod_op = PIOD_READ_AUXV; 41661.101Skamil io.piod_addr = &vector; 41671.101Skamil io.piod_len = sizeof(int); 41681.101Skamil 41691.101Skamil errno = 0; 41701.101Skamil i = 0; 41711.101Skamil /* Read the whole AUXV vector, it has no clear length */ 41721.120Skamil while (io.piod_len > 0) { 41731.101Skamil io.piod_offs = (void *)(intptr_t)i; 41741.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41751.120Skamil != -1 || (io.piod_len == 0 && i > 0)); 41761.101Skamil ++i; 41771.101Skamil } 41781.101Skamil } 41791.101Skamil 41801.101Skamil DPRINTF("Before resuming the child process where it left off " 41811.101Skamil "and without signal to be sent\n"); 41821.101Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 41831.101Skamil 41841.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41851.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 41861.101Skamil child); 41871.101Skamil 41881.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41891.101Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 41901.101Skamil} 41911.101Skamil 41921.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation) \ 41931.101SkamilATF_TC(test); \ 41941.101SkamilATF_TC_HEAD(test, tc) \ 41951.101Skamil{ \ 41961.101Skamil atf_tc_set_md_var(tc, "descr", \ 41971.101Skamil "Verify bytes transfer for potentially misaligned " \ 41981.101Skamil "operation " operation); \ 41991.101Skamil} \ 42001.101Skamil \ 42011.101SkamilATF_TC_BODY(test, tc) \ 42021.101Skamil{ \ 42031.101Skamil \ 42041.101Skamil bytes_transfer_alignment(operation); \ 42051.101Skamil} 42061.101Skamil 42071.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I") 42081.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D") 42091.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I") 42101.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D") 42111.101Skamil 42121.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I") 42131.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D") 42141.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I") 42151.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D") 42161.101Skamil 42171.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV") 42181.101Skamil 42191.101Skamil/// ---------------------------------------------------------------------------- 42201.101Skamil 42211.115Skamilstatic void 42221.115Skamilbytes_transfer_eof(const char *operation) 42231.115Skamil{ 42241.115Skamil const int exitval = 5; 42251.115Skamil const int sigval = SIGSTOP; 42261.115Skamil pid_t child, wpid; 42271.115Skamil#if defined(TWAIT_HAVE_STATUS) 42281.115Skamil int status; 42291.115Skamil#endif 42301.115Skamil FILE *fp; 42311.115Skamil char *p; 42321.115Skamil int vector; 42331.115Skamil int op; 42341.115Skamil 42351.115Skamil struct ptrace_io_desc io; 42361.115Skamil struct ptrace_siginfo info; 42371.115Skamil 42381.115Skamil memset(&io, 0, sizeof(io)); 42391.115Skamil memset(&info, 0, sizeof(info)); 42401.115Skamil 42411.115Skamil vector = 0; 42421.115Skamil 42431.115Skamil fp = tmpfile(); 42441.115Skamil ATF_REQUIRE(fp != NULL); 42451.115Skamil 42461.115Skamil p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0); 42471.115Skamil ATF_REQUIRE(p != MAP_FAILED); 42481.115Skamil 42491.115Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 42501.115Skamil SYSCALL_REQUIRE((child = fork()) != -1); 42511.115Skamil if (child == 0) { 42521.115Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 42531.115Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 42541.115Skamil 42551.115Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 42561.115Skamil FORKEE_ASSERT(raise(sigval) == 0); 42571.115Skamil 42581.115Skamil DPRINTF("Before exiting of the child process\n"); 42591.115Skamil _exit(exitval); 42601.115Skamil } 42611.115Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 42621.115Skamil 42631.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 42641.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 42651.115Skamil 42661.115Skamil validate_status_stopped(status, sigval); 42671.115Skamil 42681.115Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 42691.115Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 42701.115Skamil != -1); 42711.115Skamil 42721.115Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 42731.115Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 42741.115Skamil "si_errno=%#x\n", 42751.115Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 42761.115Skamil info.psi_siginfo.si_errno); 42771.115Skamil 42781.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 42791.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 42801.115Skamil 42811.115Skamil if (strcmp(operation, "PT_READ_I") == 0 || 42821.115Skamil strcmp(operation, "PT_READ_D") == 0) { 42831.115Skamil if (strcmp(operation, "PT_READ_I")) 42841.115Skamil op = PT_READ_I; 42851.115Skamil else 42861.115Skamil op = PT_READ_D; 42871.115Skamil 42881.115Skamil errno = 0; 42891.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, 0) == -1); 42901.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 42911.115Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 42921.115Skamil strcmp(operation, "PT_WRITE_D") == 0) { 42931.115Skamil if (strcmp(operation, "PT_WRITE_I")) 42941.115Skamil op = PT_WRITE_I; 42951.115Skamil else 42961.115Skamil op = PT_WRITE_D; 42971.115Skamil 42981.115Skamil errno = 0; 42991.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, vector) == -1); 43001.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43011.115Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 43021.115Skamil strcmp(operation, "PIOD_READ_D") == 0) { 43031.115Skamil if (strcmp(operation, "PIOD_READ_I")) 43041.115Skamil op = PIOD_READ_I; 43051.115Skamil else 43061.115Skamil op = PIOD_READ_D; 43071.115Skamil 43081.115Skamil io.piod_op = op; 43091.115Skamil io.piod_addr = &vector; 43101.115Skamil io.piod_len = sizeof(int); 43111.115Skamil io.piod_offs = p; 43121.115Skamil 43131.115Skamil errno = 0; 43141.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 43151.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43161.115Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 43171.115Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 43181.115Skamil if (strcmp(operation, "PIOD_WRITE_I")) 43191.115Skamil op = PIOD_WRITE_I; 43201.115Skamil else 43211.115Skamil op = PIOD_WRITE_D; 43221.115Skamil 43231.115Skamil io.piod_op = op; 43241.115Skamil io.piod_addr = &vector; 43251.115Skamil io.piod_len = sizeof(int); 43261.115Skamil io.piod_offs = p; 43271.115Skamil 43281.115Skamil errno = 0; 43291.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 43301.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43311.115Skamil } 43321.115Skamil 43331.115Skamil DPRINTF("Before resuming the child process where it left off " 43341.115Skamil "and without signal to be sent\n"); 43351.115Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 43361.115Skamil 43371.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43381.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 43391.115Skamil child); 43401.115Skamil 43411.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43421.115Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 43431.115Skamil} 43441.115Skamil 43451.115Skamil#define BYTES_TRANSFER_EOF(test, operation) \ 43461.115SkamilATF_TC(test); \ 43471.115SkamilATF_TC_HEAD(test, tc) \ 43481.115Skamil{ \ 43491.115Skamil atf_tc_set_md_var(tc, "descr", \ 43501.115Skamil "Verify bytes EOF byte transfer for the " operation \ 43511.115Skamil " operation"); \ 43521.115Skamil} \ 43531.115Skamil \ 43541.115SkamilATF_TC_BODY(test, tc) \ 43551.115Skamil{ \ 43561.115Skamil \ 43571.115Skamil bytes_transfer_eof(operation); \ 43581.115Skamil} 43591.115Skamil 43601.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_i, "PT_READ_I") 43611.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_d, "PT_READ_D") 43621.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_i, "PT_WRITE_I") 43631.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_d, "PT_WRITE_D") 43641.115Skamil 43651.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_i, "PIOD_READ_I") 43661.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_d, "PIOD_READ_D") 43671.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_i, "PIOD_WRITE_I") 43681.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_d, "PIOD_WRITE_D") 43691.115Skamil 43701.115Skamil/// ---------------------------------------------------------------------------- 43711.115Skamil 43721.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS) 43731.72Skamilstatic void 43741.72Skamilaccess_regs(const char *regset, const char *aux) 43751.1Skamil{ 43761.1Skamil const int exitval = 5; 43771.1Skamil const int sigval = SIGSTOP; 43781.1Skamil pid_t child, wpid; 43791.1Skamil#if defined(TWAIT_HAVE_STATUS) 43801.1Skamil int status; 43811.1Skamil#endif 43821.72Skamil#if defined(HAVE_GPREGS) 43831.72Skamil struct reg gpr; 43841.76Sscole register_t rgstr; 43851.1Skamil#endif 43861.72Skamil#if defined(HAVE_FPREGS) 43871.72Skamil struct fpreg fpr; 43881.1Skamil#endif 43891.76Sscole 43901.72Skamil#if !defined(HAVE_GPREGS) 43911.72Skamil if (strcmp(regset, "regs") == 0) 43921.72Skamil atf_tc_fail("Impossible test scenario!"); 43931.1Skamil#endif 43941.1Skamil 43951.72Skamil#if !defined(HAVE_FPREGS) 43961.72Skamil if (strcmp(regset, "fpregs") == 0) 43971.72Skamil atf_tc_fail("Impossible test scenario!"); 43981.1Skamil#endif 43991.1Skamil 44001.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 44011.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 44021.1Skamil if (child == 0) { 44031.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 44041.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 44051.1Skamil 44061.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 44071.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 44081.1Skamil 44091.13Schristos DPRINTF("Before exiting of the child process\n"); 44101.1Skamil _exit(exitval); 44111.1Skamil } 44121.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 44131.1Skamil 44141.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44151.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44161.1Skamil 44171.1Skamil validate_status_stopped(status, sigval); 44181.1Skamil 44191.1Skamil#if defined(HAVE_GPREGS) 44201.72Skamil if (strcmp(regset, "regs") == 0) { 44211.72Skamil DPRINTF("Call GETREGS for the child process\n"); 44221.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1); 44231.72Skamil 44241.72Skamil if (strcmp(aux, "none") == 0) { 44251.72Skamil DPRINTF("Retrieved registers\n"); 44261.72Skamil } else if (strcmp(aux, "pc") == 0) { 44271.72Skamil rgstr = PTRACE_REG_PC(&gpr); 44281.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44291.72Skamil } else if (strcmp(aux, "set_pc") == 0) { 44301.72Skamil rgstr = PTRACE_REG_PC(&gpr); 44311.72Skamil PTRACE_REG_SET_PC(&gpr, rgstr); 44321.72Skamil } else if (strcmp(aux, "sp") == 0) { 44331.72Skamil rgstr = PTRACE_REG_SP(&gpr); 44341.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44351.72Skamil } else if (strcmp(aux, "intrv") == 0) { 44361.72Skamil rgstr = PTRACE_REG_INTRV(&gpr); 44371.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44381.72Skamil } else if (strcmp(aux, "setregs") == 0) { 44391.72Skamil DPRINTF("Call SETREGS for the child process\n"); 44401.72Skamil SYSCALL_REQUIRE( 44411.72Skamil ptrace(PT_GETREGS, child, &gpr, 0) != -1); 44421.72Skamil } 44431.72Skamil } 44441.1Skamil#endif 44451.1Skamil 44461.72Skamil#if defined(HAVE_FPREGS) 44471.72Skamil if (strcmp(regset, "fpregs") == 0) { 44481.72Skamil DPRINTF("Call GETFPREGS for the child process\n"); 44491.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1); 44501.72Skamil 44511.72Skamil if (strcmp(aux, "getfpregs") == 0) { 44521.72Skamil DPRINTF("Retrieved FP registers\n"); 44531.72Skamil } else if (strcmp(aux, "setfpregs") == 0) { 44541.72Skamil DPRINTF("Call SETFPREGS for the child\n"); 44551.72Skamil SYSCALL_REQUIRE( 44561.72Skamil ptrace(PT_SETFPREGS, child, &fpr, 0) != -1); 44571.72Skamil } 44581.1Skamil } 44591.1Skamil#endif 44601.1Skamil 44611.13Schristos DPRINTF("Before resuming the child process where it left off and " 44621.1Skamil "without signal to be sent\n"); 44631.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 44641.1Skamil 44651.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44661.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44671.1Skamil 44681.1Skamil validate_status_exited(status, exitval); 44691.1Skamil 44701.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44711.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 44721.1Skamil} 44731.1Skamil 44741.72Skamil#define ACCESS_REGS(test, regset, aux) \ 44751.72SkamilATF_TC(test); \ 44761.72SkamilATF_TC_HEAD(test, tc) \ 44771.72Skamil{ \ 44781.72Skamil atf_tc_set_md_var(tc, "descr", \ 44791.72Skamil "Verify " regset " with auxiliary operation: " aux); \ 44801.72Skamil} \ 44811.72Skamil \ 44821.72SkamilATF_TC_BODY(test, tc) \ 44831.72Skamil{ \ 44841.72Skamil \ 44851.72Skamil access_regs(regset, aux); \ 44861.1Skamil} 44871.1Skamil#endif 44881.1Skamil 44891.72Skamil#if defined(HAVE_GPREGS) 44901.72SkamilACCESS_REGS(access_regs1, "regs", "none") 44911.72SkamilACCESS_REGS(access_regs2, "regs", "pc") 44921.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc") 44931.72SkamilACCESS_REGS(access_regs4, "regs", "sp") 44941.72SkamilACCESS_REGS(access_regs5, "regs", "intrv") 44951.72SkamilACCESS_REGS(access_regs6, "regs", "setregs") 44961.1Skamil#endif 44971.1Skamil#if defined(HAVE_FPREGS) 44981.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs") 44991.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs") 45001.1Skamil#endif 45011.1Skamil 45021.72Skamil/// ---------------------------------------------------------------------------- 45031.1Skamil 45041.1Skamil#if defined(PT_STEP) 45051.1Skamilstatic void 45061.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored) 45071.1Skamil{ 45081.1Skamil const int exitval = 5; 45091.1Skamil const int sigval = SIGSTOP; 45101.1Skamil pid_t child, wpid; 45111.1Skamil#if defined(TWAIT_HAVE_STATUS) 45121.1Skamil int status; 45131.1Skamil#endif 45141.1Skamil int happy; 45151.95Skamil struct sigaction sa; 45161.81Skamil struct ptrace_siginfo info; 45171.95Skamil sigset_t intmask; 45181.95Skamil struct kinfo_proc2 kp; 45191.95Skamil size_t len = sizeof(kp); 45201.95Skamil 45211.95Skamil int name[6]; 45221.95Skamil const size_t namelen = __arraycount(name); 45231.95Skamil ki_sigset_t kp_sigmask; 45241.95Skamil ki_sigset_t kp_sigignore; 45251.1Skamil 45261.1Skamil#if defined(__arm__) 45271.1Skamil /* PT_STEP not supported on arm 32-bit */ 45281.1Skamil atf_tc_expect_fail("PR kern/52119"); 45291.1Skamil#endif 45301.1Skamil 45311.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 45321.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 45331.1Skamil if (child == 0) { 45341.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 45351.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 45361.1Skamil 45371.95Skamil if (masked) { 45381.95Skamil sigemptyset(&intmask); 45391.95Skamil sigaddset(&intmask, SIGTRAP); 45401.95Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 45411.95Skamil } 45421.95Skamil 45431.95Skamil if (ignored) { 45441.95Skamil memset(&sa, 0, sizeof(sa)); 45451.95Skamil sa.sa_handler = SIG_IGN; 45461.95Skamil sigemptyset(&sa.sa_mask); 45471.95Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 45481.95Skamil } 45491.95Skamil 45501.1Skamil happy = check_happy(999); 45511.1Skamil 45521.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 45531.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 45541.1Skamil 45551.1Skamil FORKEE_ASSERT_EQ(happy, check_happy(999)); 45561.1Skamil 45571.13Schristos DPRINTF("Before exiting of the child process\n"); 45581.1Skamil _exit(exitval); 45591.1Skamil } 45601.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 45611.1Skamil 45621.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45631.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 45641.1Skamil 45651.1Skamil validate_status_stopped(status, sigval); 45661.1Skamil 45671.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 45681.81Skamil SYSCALL_REQUIRE( 45691.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 45701.81Skamil 45711.81Skamil DPRINTF("Before checking siginfo_t\n"); 45721.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 45731.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 45741.81Skamil 45751.95Skamil name[0] = CTL_KERN, 45761.95Skamil name[1] = KERN_PROC2, 45771.95Skamil name[2] = KERN_PROC_PID; 45781.95Skamil name[3] = child; 45791.95Skamil name[4] = sizeof(kp); 45801.95Skamil name[5] = 1; 45811.95Skamil 45821.95Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 45831.95Skamil 45841.95Skamil if (masked) 45851.95Skamil kp_sigmask = kp.p_sigmask; 45861.95Skamil 45871.95Skamil if (ignored) 45881.95Skamil kp_sigignore = kp.p_sigignore; 45891.95Skamil 45901.1Skamil while (N --> 0) { 45911.2Skamil if (setstep) { 45921.13Schristos DPRINTF("Before resuming the child process where it " 45931.2Skamil "left off and without signal to be sent (use " 45941.9Skamil "PT_SETSTEP and PT_CONTINUE)\n"); 45951.13Schristos SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1); 45961.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) 45971.2Skamil != -1); 45981.2Skamil } else { 45991.13Schristos DPRINTF("Before resuming the child process where it " 46001.2Skamil "left off and without signal to be sent (use " 46011.2Skamil "PT_STEP)\n"); 46021.13Schristos SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) 46031.2Skamil != -1); 46041.2Skamil } 46051.1Skamil 46061.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46071.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 46081.1Skamil child); 46091.1Skamil 46101.1Skamil validate_status_stopped(status, SIGTRAP); 46111.2Skamil 46121.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 46131.81Skamil SYSCALL_REQUIRE( 46141.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 46151.81Skamil 46161.81Skamil DPRINTF("Before checking siginfo_t\n"); 46171.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 46181.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE); 46191.81Skamil 46201.2Skamil if (setstep) { 46211.13Schristos SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1); 46221.2Skamil } 46231.95Skamil 46241.95Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 46251.95Skamil 46261.95Skamil if (masked) { 46271.95Skamil DPRINTF("kp_sigmask=" 46281.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46291.95Skamil PRIx32 "\n", 46301.95Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 46311.95Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 46321.95Skamil 46331.95Skamil DPRINTF("kp.p_sigmask=" 46341.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46351.95Skamil PRIx32 "\n", 46361.95Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 46371.95Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 46381.95Skamil 46391.95Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 46401.95Skamil sizeof(kp_sigmask))); 46411.95Skamil } 46421.95Skamil 46431.95Skamil if (ignored) { 46441.95Skamil DPRINTF("kp_sigignore=" 46451.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46461.95Skamil PRIx32 "\n", 46471.95Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 46481.95Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 46491.95Skamil 46501.95Skamil DPRINTF("kp.p_sigignore=" 46511.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46521.95Skamil PRIx32 "\n", 46531.95Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 46541.95Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 46551.95Skamil 46561.95Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 46571.95Skamil sizeof(kp_sigignore))); 46581.95Skamil } 46591.1Skamil } 46601.1Skamil 46611.13Schristos DPRINTF("Before resuming the child process where it left off and " 46621.1Skamil "without signal to be sent\n"); 46631.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 46641.1Skamil 46651.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46661.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 46671.1Skamil 46681.1Skamil validate_status_exited(status, exitval); 46691.1Skamil 46701.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46711.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 46721.1Skamil} 46731.1Skamil 46741.73Skamil#define PTRACE_STEP(test, N, setstep) \ 46751.73SkamilATF_TC(test); \ 46761.73SkamilATF_TC_HEAD(test, tc) \ 46771.73Skamil{ \ 46781.73Skamil atf_tc_set_md_var(tc, "descr", \ 46791.74Skamil "Verify " #N " (PT_SETSTEP set to: " #setstep ")"); \ 46801.73Skamil} \ 46811.73Skamil \ 46821.73SkamilATF_TC_BODY(test, tc) \ 46831.73Skamil{ \ 46841.73Skamil \ 46851.95Skamil ptrace_step(N, setstep, false, false); \ 46861.1Skamil} 46871.1Skamil 46881.73SkamilPTRACE_STEP(step1, 1, 0) 46891.73SkamilPTRACE_STEP(step2, 2, 0) 46901.73SkamilPTRACE_STEP(step3, 3, 0) 46911.73SkamilPTRACE_STEP(step4, 4, 0) 46921.73SkamilPTRACE_STEP(setstep1, 1, 1) 46931.73SkamilPTRACE_STEP(setstep2, 2, 1) 46941.73SkamilPTRACE_STEP(setstep3, 3, 1) 46951.73SkamilPTRACE_STEP(setstep4, 4, 1) 46961.95Skamil 46971.95SkamilATF_TC(step_signalmasked); 46981.95SkamilATF_TC_HEAD(step_signalmasked, tc) 46991.95Skamil{ 47001.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP"); 47011.95Skamil} 47021.95Skamil 47031.95SkamilATF_TC_BODY(step_signalmasked, tc) 47041.95Skamil{ 47051.95Skamil 47061.95Skamil ptrace_step(1, 0, true, false); 47071.95Skamil} 47081.95Skamil 47091.95SkamilATF_TC(step_signalignored); 47101.95SkamilATF_TC_HEAD(step_signalignored, tc) 47111.95Skamil{ 47121.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP"); 47131.95Skamil} 47141.95Skamil 47151.95SkamilATF_TC_BODY(step_signalignored, tc) 47161.95Skamil{ 47171.95Skamil 47181.95Skamil ptrace_step(1, 0, false, true); 47191.95Skamil} 47201.1Skamil#endif 47211.1Skamil 47221.73Skamil/// ---------------------------------------------------------------------------- 47231.1Skamil 47241.75Skamilstatic void 47251.75Skamilptrace_kill(const char *type) 47261.1Skamil{ 47271.75Skamil const int sigval = SIGSTOP; 47281.1Skamil pid_t child, wpid; 47291.1Skamil#if defined(TWAIT_HAVE_STATUS) 47301.1Skamil int status; 47311.1Skamil#endif 47321.1Skamil 47331.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 47341.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 47351.1Skamil if (child == 0) { 47361.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 47371.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 47381.1Skamil 47391.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 47401.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 47411.1Skamil 47421.1Skamil /* NOTREACHED */ 47431.1Skamil FORKEE_ASSERTX(0 && 47441.1Skamil "Child should be terminated by a signal from its parent"); 47451.1Skamil } 47461.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 47471.1Skamil 47481.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47491.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47501.1Skamil 47511.1Skamil validate_status_stopped(status, sigval); 47521.1Skamil 47531.75Skamil DPRINTF("Before killing the child process with %s\n", type); 47541.75Skamil if (strcmp(type, "ptrace(PT_KILL)") == 0) { 47551.75Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1); 47561.75Skamil } else if (strcmp(type, "kill(SIGKILL)") == 0) { 47571.75Skamil kill(child, SIGKILL); 47581.75Skamil } else if (strcmp(type, "killpg(SIGKILL)") == 0) { 47591.75Skamil setpgid(child, 0); 47601.75Skamil killpg(getpgid(child), SIGKILL); 47611.75Skamil } 47621.1Skamil 47631.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47641.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47651.1Skamil 47661.75Skamil validate_status_signaled(status, SIGKILL, 0); 47671.1Skamil 47681.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47691.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 47701.1Skamil} 47711.1Skamil 47721.75Skamil#define PTRACE_KILL(test, type) \ 47731.75SkamilATF_TC(test); \ 47741.75SkamilATF_TC_HEAD(test, tc) \ 47751.75Skamil{ \ 47761.75Skamil atf_tc_set_md_var(tc, "descr", \ 47771.75Skamil "Verify killing the child with " type); \ 47781.75Skamil} \ 47791.75Skamil \ 47801.75SkamilATF_TC_BODY(test, tc) \ 47811.75Skamil{ \ 47821.75Skamil \ 47831.75Skamil ptrace_kill(type); \ 47841.1Skamil} 47851.1Skamil 47861.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1 47871.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)") 47881.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)") 47891.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)") 47901.1Skamil 47911.75Skamil/// ---------------------------------------------------------------------------- 47921.1Skamil 47931.77Skamilstatic void 47941.77Skamiltraceme_lwpinfo(const int threads) 47951.1Skamil{ 47961.1Skamil const int sigval = SIGSTOP; 47971.77Skamil const int sigval2 = SIGINT; 47981.1Skamil pid_t child, wpid; 47991.1Skamil#if defined(TWAIT_HAVE_STATUS) 48001.1Skamil int status; 48011.1Skamil#endif 48021.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 48031.77Skamil struct ptrace_siginfo info; 48041.77Skamil 48051.77Skamil /* Maximum number of supported threads in this test */ 48061.77Skamil pthread_t t[3]; 48071.77Skamil int n, rv; 48081.77Skamil 48091.77Skamil ATF_REQUIRE((int)__arraycount(t) >= threads); 48101.1Skamil 48111.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 48121.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 48131.1Skamil if (child == 0) { 48141.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 48151.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 48161.1Skamil 48171.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 48181.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 48191.1Skamil 48201.77Skamil for (n = 0; n < threads; n++) { 48211.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 48221.77Skamil FORKEE_ASSERT(rv == 0); 48231.77Skamil } 48241.77Skamil 48251.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval2)); 48261.77Skamil FORKEE_ASSERT(raise(sigval2) == 0); 48271.77Skamil 48281.77Skamil /* NOTREACHED */ 48291.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 48301.1Skamil } 48311.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 48321.1Skamil 48331.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48341.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48351.1Skamil 48361.1Skamil validate_status_stopped(status, sigval); 48371.1Skamil 48381.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 48391.77Skamil SYSCALL_REQUIRE( 48401.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 48411.77Skamil 48421.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 48431.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 48441.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 48451.77Skamil info.psi_siginfo.si_errno); 48461.77Skamil 48471.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 48481.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 48491.77Skamil 48501.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48511.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48521.1Skamil 48531.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 48541.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 48551.1Skamil 48561.13Schristos DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n", 48571.77Skamil lwp.pl_lwpid); 48581.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 48591.1Skamil 48601.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48611.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48621.1Skamil 48631.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 48641.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 48651.1Skamil 48661.13Schristos DPRINTF("Before resuming the child process where it left off and " 48671.1Skamil "without signal to be sent\n"); 48681.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 48691.1Skamil 48701.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48711.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48721.1Skamil 48731.77Skamil validate_status_stopped(status, sigval2); 48741.77Skamil 48751.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 48761.77Skamil SYSCALL_REQUIRE( 48771.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 48781.77Skamil 48791.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 48801.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 48811.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 48821.77Skamil info.psi_siginfo.si_errno); 48831.77Skamil 48841.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2); 48851.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 48861.77Skamil 48871.77Skamil memset(&lwp, 0, sizeof(lwp)); 48881.77Skamil 48891.77Skamil for (n = 0; n <= threads; n++) { 48901.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48911.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48921.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 48931.77Skamil 48941.77Skamil DPRINTF("Assert that the thread exists\n"); 48951.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 48961.77Skamil 48971.77Skamil DPRINTF("Assert that lwp thread %d received expected event\n", 48981.77Skamil lwp.pl_lwpid); 48991.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ? 49001.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 49011.77Skamil } 49021.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 49031.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 49041.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 49051.77Skamil 49061.77Skamil DPRINTF("Assert that there are no more threads\n"); 49071.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 49081.77Skamil 49091.77Skamil DPRINTF("Before resuming the child process where it left off and " 49101.77Skamil "without signal to be sent\n"); 49111.77Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1); 49121.77Skamil 49131.77Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49141.77Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 49151.77Skamil 49161.77Skamil validate_status_signaled(status, SIGKILL, 0); 49171.1Skamil 49181.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49191.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 49201.1Skamil} 49211.1Skamil 49221.77Skamil#define TRACEME_LWPINFO(test, threads) \ 49231.77SkamilATF_TC(test); \ 49241.77SkamilATF_TC_HEAD(test, tc) \ 49251.77Skamil{ \ 49261.77Skamil atf_tc_set_md_var(tc, "descr", \ 49271.77Skamil "Verify LWPINFO with the child with " #threads \ 49281.77Skamil " spawned extra threads"); \ 49291.77Skamil} \ 49301.77Skamil \ 49311.77SkamilATF_TC_BODY(test, tc) \ 49321.77Skamil{ \ 49331.77Skamil \ 49341.77Skamil traceme_lwpinfo(threads); \ 49351.1Skamil} 49361.1Skamil 49371.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0) 49381.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1) 49391.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2) 49401.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3) 49411.77Skamil 49421.77Skamil/// ---------------------------------------------------------------------------- 49431.77Skamil 49441.77Skamil#if defined(TWAIT_HAVE_PID) 49451.77Skamilstatic void 49461.77Skamilattach_lwpinfo(const int threads) 49471.1Skamil{ 49481.77Skamil const int sigval = SIGINT; 49491.1Skamil struct msg_fds parent_tracee, parent_tracer; 49501.1Skamil const int exitval_tracer = 10; 49511.1Skamil pid_t tracee, tracer, wpid; 49521.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 49531.1Skamil#if defined(TWAIT_HAVE_STATUS) 49541.1Skamil int status; 49551.1Skamil#endif 49561.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 49571.77Skamil struct ptrace_siginfo info; 49581.77Skamil 49591.77Skamil /* Maximum number of supported threads in this test */ 49601.77Skamil pthread_t t[3]; 49611.77Skamil int n, rv; 49621.1Skamil 49631.13Schristos DPRINTF("Spawn tracee\n"); 49641.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 49651.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 49661.1Skamil tracee = atf_utils_fork(); 49671.1Skamil if (tracee == 0) { 49681.1Skamil /* Wait for message from the parent */ 49691.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 49701.1Skamil 49711.77Skamil CHILD_FROM_PARENT("spawn threads", parent_tracee, msg); 49721.77Skamil 49731.77Skamil for (n = 0; n < threads; n++) { 49741.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 49751.77Skamil FORKEE_ASSERT(rv == 0); 49761.77Skamil } 49771.77Skamil 49781.77Skamil CHILD_TO_PARENT("tracee exit", parent_tracee, msg); 49791.77Skamil 49801.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 49811.77Skamil FORKEE_ASSERT(raise(sigval) == 0); 49821.77Skamil 49831.77Skamil /* NOTREACHED */ 49841.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 49851.1Skamil } 49861.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 49871.1Skamil 49881.13Schristos DPRINTF("Spawn debugger\n"); 49891.1Skamil tracer = atf_utils_fork(); 49901.1Skamil if (tracer == 0) { 49911.1Skamil /* No IPC to communicate with the child */ 49921.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 49931.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 49941.1Skamil 49951.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 49961.1Skamil FORKEE_REQUIRE_SUCCESS( 49971.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 49981.1Skamil 49991.1Skamil forkee_status_stopped(status, SIGSTOP); 50001.1Skamil 50011.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 50021.77Skamil "tracee"); 50031.77Skamil FORKEE_ASSERT( 50041.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 50051.77Skamil 50061.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 50071.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 50081.77Skamil "si_errno=%#x\n", 50091.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 50101.77Skamil info.psi_siginfo.si_errno); 50111.77Skamil 50121.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 50131.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 50141.77Skamil 50151.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 50161.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 50171.1Skamil != -1); 50181.1Skamil 50191.13Schristos DPRINTF("Assert that there exists a thread\n"); 50201.77Skamil FORKEE_ASSERTX(lwp.pl_lwpid > 0); 50211.1Skamil 50221.13Schristos DPRINTF("Assert that lwp thread %d received event " 50231.77Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 50241.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 50251.1Skamil 50261.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50271.77Skamil "tracee\n"); 50281.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 50291.1Skamil != -1); 50301.1Skamil 50311.77Skamil DPRINTF("Assert that there are no more lwp threads in " 50321.77Skamil "tracee\n"); 50331.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 50341.1Skamil 50351.1Skamil /* Resume tracee with PT_CONTINUE */ 50361.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 50371.1Skamil 50381.1Skamil /* Inform parent that tracer has attached to tracee */ 50391.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 50401.77Skamil 50411.1Skamil /* Wait for parent */ 50421.1Skamil CHILD_FROM_PARENT("tracer wait", parent_tracer, msg); 50431.1Skamil 50441.77Skamil /* Wait for tracee and assert that it raised a signal */ 50451.77Skamil FORKEE_REQUIRE_SUCCESS( 50461.77Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 50471.77Skamil 50481.77Skamil forkee_status_stopped(status, SIGINT); 50491.77Skamil 50501.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 50511.77Skamil "child"); 50521.77Skamil FORKEE_ASSERT( 50531.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 50541.77Skamil 50551.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 50561.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 50571.77Skamil "si_errno=%#x\n", 50581.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 50591.77Skamil info.psi_siginfo.si_errno); 50601.77Skamil 50611.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 50621.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 50631.77Skamil 50641.77Skamil memset(&lwp, 0, sizeof(lwp)); 50651.77Skamil 50661.77Skamil for (n = 0; n <= threads; n++) { 50671.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50681.77Skamil "child\n"); 50691.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, 50701.77Skamil sizeof(lwp)) != -1); 50711.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 50721.77Skamil 50731.77Skamil DPRINTF("Assert that the thread exists\n"); 50741.77Skamil FORKEE_ASSERT(lwp.pl_lwpid > 0); 50751.77Skamil 50761.77Skamil DPRINTF("Assert that lwp thread %d received expected " 50771.77Skamil "event\n", lwp.pl_lwpid); 50781.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 50791.77Skamil info.psi_lwpid == lwp.pl_lwpid ? 50801.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 50811.77Skamil } 50821.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50831.77Skamil "tracee\n"); 50841.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 50851.77Skamil != -1); 50861.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 50871.77Skamil 50881.77Skamil DPRINTF("Assert that there are no more threads\n"); 50891.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 50901.77Skamil 50911.77Skamil DPRINTF("Before resuming the child process where it left off " 50921.77Skamil "and without signal to be sent\n"); 50931.77Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL) 50941.77Skamil != -1); 50951.77Skamil 50961.1Skamil /* Wait for tracee and assert that it exited */ 50971.1Skamil FORKEE_REQUIRE_SUCCESS( 50981.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 50991.1Skamil 51001.77Skamil forkee_status_signaled(status, SIGKILL, 0); 51011.1Skamil 51021.13Schristos DPRINTF("Before exiting of the tracer process\n"); 51031.1Skamil _exit(exitval_tracer); 51041.1Skamil } 51051.1Skamil 51061.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 51071.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 51081.1Skamil 51091.77Skamil DPRINTF("Resume the tracee and spawn threads\n"); 51101.77Skamil PARENT_TO_CHILD("spawn threads", parent_tracee, msg); 51111.77Skamil 51121.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 51131.77Skamil PARENT_FROM_CHILD("tracee exit", parent_tracee, msg); 51141.1Skamil 51151.77Skamil DPRINTF("Resume the tracer and let it detect multiple threads\n"); 51161.1Skamil PARENT_TO_CHILD("tracer wait", parent_tracer, msg); 51171.1Skamil 51181.13Schristos DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n", 51191.1Skamil TWAIT_FNAME); 51201.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 51211.1Skamil tracer); 51221.1Skamil 51231.1Skamil validate_status_exited(status, exitval_tracer); 51241.1Skamil 51251.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 51261.1Skamil TWAIT_FNAME); 51271.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 51281.1Skamil tracee); 51291.1Skamil 51301.77Skamil validate_status_signaled(status, SIGKILL, 0); 51311.1Skamil 51321.1Skamil msg_close(&parent_tracer); 51331.1Skamil msg_close(&parent_tracee); 51341.1Skamil} 51351.77Skamil 51361.77Skamil#define ATTACH_LWPINFO(test, threads) \ 51371.77SkamilATF_TC(test); \ 51381.77SkamilATF_TC_HEAD(test, tc) \ 51391.77Skamil{ \ 51401.77Skamil atf_tc_set_md_var(tc, "descr", \ 51411.77Skamil "Verify LWPINFO with the child with " #threads \ 51421.77Skamil " spawned extra threads (tracer is not the original " \ 51431.77Skamil "parent)"); \ 51441.77Skamil} \ 51451.77Skamil \ 51461.77SkamilATF_TC_BODY(test, tc) \ 51471.77Skamil{ \ 51481.77Skamil \ 51491.77Skamil attach_lwpinfo(threads); \ 51501.77Skamil} 51511.77Skamil 51521.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0) 51531.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1) 51541.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2) 51551.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3) 51561.1Skamil#endif 51571.1Skamil 51581.77Skamil/// ---------------------------------------------------------------------------- 51591.77Skamil 51601.1Skamilstatic void 51611.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught) 51621.1Skamil{ 51631.1Skamil const int exitval = 5; 51641.1Skamil const int sigval = SIGINT; 51651.1Skamil const int sigfaked = SIGTRAP; 51661.1Skamil const int sicodefaked = TRAP_BRKPT; 51671.1Skamil pid_t child, wpid; 51681.1Skamil struct sigaction sa; 51691.1Skamil#if defined(TWAIT_HAVE_STATUS) 51701.1Skamil int status; 51711.1Skamil#endif 51721.1Skamil struct ptrace_siginfo info; 51731.1Skamil memset(&info, 0, sizeof(info)); 51741.1Skamil 51751.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 51761.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 51771.1Skamil if (child == 0) { 51781.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 51791.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 51801.1Skamil 51811.79Skamil sa.sa_sigaction = sah; 51821.1Skamil sa.sa_flags = SA_SIGINFO; 51831.1Skamil sigemptyset(&sa.sa_mask); 51841.1Skamil 51851.79Skamil FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL) 51861.79Skamil != -1); 51871.1Skamil 51881.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 51891.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 51901.1Skamil 51911.79Skamil FORKEE_ASSERT_EQ(*signal_caught, 1); 51921.1Skamil 51931.13Schristos DPRINTF("Before exiting of the child process\n"); 51941.1Skamil _exit(exitval); 51951.1Skamil } 51961.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 51971.1Skamil 51981.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51991.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52001.1Skamil 52011.1Skamil validate_status_stopped(status, sigval); 52021.1Skamil 52031.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 52041.61Skre SYSCALL_REQUIRE( 52051.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 52061.1Skamil 52071.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 52081.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 52091.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 52101.1Skamil info.psi_siginfo.si_errno); 52111.1Skamil 52121.79Skamil if (faked) { 52131.79Skamil DPRINTF("Before setting new faked signal to signo=%d " 52141.79Skamil "si_code=%d\n", sigfaked, sicodefaked); 52151.79Skamil info.psi_siginfo.si_signo = sigfaked; 52161.79Skamil info.psi_siginfo.si_code = sicodefaked; 52171.79Skamil } 52181.1Skamil 52191.13Schristos DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n"); 52201.61Skre SYSCALL_REQUIRE( 52211.61Skre ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1); 52221.1Skamil 52231.79Skamil if (faked) { 52241.79Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 52251.79Skamil "child\n"); 52261.79Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 52271.79Skamil sizeof(info)) != -1); 52281.1Skamil 52291.79Skamil DPRINTF("Before checking siginfo_t\n"); 52301.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked); 52311.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked); 52321.79Skamil } 52331.1Skamil 52341.13Schristos DPRINTF("Before resuming the child process where it left off and " 52351.1Skamil "without signal to be sent\n"); 52361.79Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 52371.79Skamil faked ? sigfaked : sigval) != -1); 52381.1Skamil 52391.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52401.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52411.1Skamil 52421.1Skamil validate_status_exited(status, exitval); 52431.1Skamil 52441.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52451.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 52461.1Skamil} 52471.1Skamil 52481.79Skamil#define PTRACE_SIGINFO(test, faked) \ 52491.79SkamilATF_TC(test); \ 52501.79SkamilATF_TC_HEAD(test, tc) \ 52511.79Skamil{ \ 52521.79Skamil atf_tc_set_md_var(tc, "descr", \ 52531.79Skamil "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls" \ 52541.79Skamil "with%s setting signal to new value", faked ? "" : "out"); \ 52551.79Skamil} \ 52561.79Skamil \ 52571.79Skamilstatic int test##_caught = 0; \ 52581.79Skamil \ 52591.79Skamilstatic void \ 52601.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx) \ 52611.79Skamil{ \ 52621.79Skamil if (faked) { \ 52631.79Skamil FORKEE_ASSERT_EQ(sig, SIGTRAP); \ 52641.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP); \ 52651.79Skamil FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT); \ 52661.79Skamil } else { \ 52671.79Skamil FORKEE_ASSERT_EQ(sig, SIGINT); \ 52681.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGINT); \ 52691.79Skamil FORKEE_ASSERT_EQ(info->si_code, SI_LWP); \ 52701.79Skamil } \ 52711.79Skamil \ 52721.79Skamil ++ test##_caught; \ 52731.79Skamil} \ 52741.79Skamil \ 52751.79SkamilATF_TC_BODY(test, tc) \ 52761.79Skamil{ \ 52771.79Skamil \ 52781.79Skamil ptrace_siginfo(faked, test##_sighandler, & test##_caught); \ 52791.79Skamil} 52801.79Skamil 52811.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false) 52821.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true) 52831.79Skamil 52841.79Skamil/// ---------------------------------------------------------------------------- 52851.79Skamil 52861.97Skamilstatic void 52871.97Skamiltraceme_exec(bool masked, bool ignored) 52881.1Skamil{ 52891.1Skamil const int sigval = SIGTRAP; 52901.1Skamil pid_t child, wpid; 52911.1Skamil#if defined(TWAIT_HAVE_STATUS) 52921.1Skamil int status; 52931.1Skamil#endif 52941.97Skamil struct sigaction sa; 52951.97Skamil struct ptrace_siginfo info; 52961.97Skamil sigset_t intmask; 52971.97Skamil struct kinfo_proc2 kp; 52981.97Skamil size_t len = sizeof(kp); 52991.97Skamil 53001.97Skamil int name[6]; 53011.97Skamil const size_t namelen = __arraycount(name); 53021.97Skamil ki_sigset_t kp_sigmask; 53031.97Skamil ki_sigset_t kp_sigignore; 53041.1Skamil 53051.1Skamil memset(&info, 0, sizeof(info)); 53061.1Skamil 53071.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 53081.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 53091.1Skamil if (child == 0) { 53101.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 53111.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 53121.1Skamil 53131.97Skamil if (masked) { 53141.97Skamil sigemptyset(&intmask); 53151.97Skamil sigaddset(&intmask, sigval); 53161.97Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 53171.97Skamil } 53181.97Skamil 53191.97Skamil if (ignored) { 53201.97Skamil memset(&sa, 0, sizeof(sa)); 53211.97Skamil sa.sa_handler = SIG_IGN; 53221.97Skamil sigemptyset(&sa.sa_mask); 53231.97Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 53241.97Skamil } 53251.97Skamil 53261.13Schristos DPRINTF("Before calling execve(2) from child\n"); 53271.1Skamil execlp("/bin/echo", "/bin/echo", NULL); 53281.1Skamil 53291.1Skamil FORKEE_ASSERT(0 && "Not reached"); 53301.1Skamil } 53311.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 53321.1Skamil 53331.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53341.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 53351.1Skamil 53361.1Skamil validate_status_stopped(status, sigval); 53371.1Skamil 53381.97Skamil name[0] = CTL_KERN, 53391.97Skamil name[1] = KERN_PROC2, 53401.97Skamil name[2] = KERN_PROC_PID; 53411.97Skamil name[3] = getpid(); 53421.97Skamil name[4] = sizeof(kp); 53431.97Skamil name[5] = 1; 53441.97Skamil 53451.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 53461.97Skamil 53471.97Skamil if (masked) 53481.97Skamil kp_sigmask = kp.p_sigmask; 53491.97Skamil 53501.97Skamil if (ignored) 53511.97Skamil kp_sigignore = kp.p_sigignore; 53521.97Skamil 53531.97Skamil name[3] = getpid(); 53541.97Skamil 53551.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 53561.97Skamil 53571.97Skamil if (masked) { 53581.97Skamil DPRINTF("kp_sigmask=" 53591.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53601.97Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 53611.97Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 53621.97Skamil 53631.97Skamil DPRINTF("kp.p_sigmask=" 53641.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53651.97Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 53661.97Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 53671.97Skamil 53681.97Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 53691.97Skamil sizeof(kp_sigmask))); 53701.97Skamil } 53711.97Skamil 53721.97Skamil if (ignored) { 53731.97Skamil DPRINTF("kp_sigignore=" 53741.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53751.97Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 53761.97Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 53771.97Skamil 53781.97Skamil DPRINTF("kp.p_sigignore=" 53791.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53801.97Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 53811.97Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 53821.97Skamil 53831.97Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 53841.97Skamil sizeof(kp_sigignore))); 53851.97Skamil } 53861.97Skamil 53871.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 53881.61Skre SYSCALL_REQUIRE( 53891.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 53901.1Skamil 53911.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 53921.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 53931.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 53941.1Skamil info.psi_siginfo.si_errno); 53951.1Skamil 53961.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 53971.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 53981.1Skamil 53991.13Schristos DPRINTF("Before resuming the child process where it left off and " 54001.1Skamil "without signal to be sent\n"); 54011.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 54021.1Skamil 54031.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54041.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 54051.1Skamil 54061.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54071.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 54081.1Skamil} 54091.1Skamil 54101.97Skamil#define TRACEME_EXEC(test, masked, ignored) \ 54111.97SkamilATF_TC(test); \ 54121.97SkamilATF_TC_HEAD(test, tc) \ 54131.97Skamil{ \ 54141.97Skamil atf_tc_set_md_var(tc, "descr", \ 54151.97Skamil "Detect SIGTRAP TRAP_EXEC from " \ 54161.97Skamil "child%s%s", masked ? " with masked signal" : "", \ 54171.97Skamil masked ? " with ignored signal" : ""); \ 54181.97Skamil} \ 54191.97Skamil \ 54201.97SkamilATF_TC_BODY(test, tc) \ 54211.97Skamil{ \ 54221.97Skamil \ 54231.97Skamil traceme_exec(masked, ignored); \ 54241.97Skamil} 54251.97Skamil 54261.97SkamilTRACEME_EXEC(traceme_exec, false, false) 54271.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false) 54281.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true) 54291.97Skamil 54301.82Skamil/// ---------------------------------------------------------------------------- 54311.82Skamil 54321.83Skamilstatic volatile int done; 54331.1Skamil 54341.83Skamilstatic void * 54351.83Skamiltrace_threads_cb(void *arg __unused) 54361.1Skamil{ 54371.1Skamil 54381.83Skamil done++; 54391.83Skamil 54401.83Skamil while (done < 3) 54411.83Skamil continue; 54421.83Skamil 54431.83Skamil return NULL; 54441.1Skamil} 54451.1Skamil 54461.83Skamilstatic void 54471.83Skamiltrace_threads(bool trace_create, bool trace_exit) 54481.1Skamil{ 54491.1Skamil const int sigval = SIGSTOP; 54501.1Skamil pid_t child, wpid; 54511.1Skamil#if defined(TWAIT_HAVE_STATUS) 54521.1Skamil int status; 54531.1Skamil#endif 54541.1Skamil ptrace_state_t state; 54551.1Skamil const int slen = sizeof(state); 54561.1Skamil ptrace_event_t event; 54571.1Skamil const int elen = sizeof(event); 54581.83Skamil struct ptrace_siginfo info; 54591.83Skamil 54601.83Skamil pthread_t t[3]; 54611.83Skamil int rv; 54621.83Skamil size_t n; 54631.1Skamil lwpid_t lid; 54641.83Skamil 54651.83Skamil /* Track created and exited threads */ 54661.83Skamil bool traced_lwps[__arraycount(t)]; 54671.83Skamil 54681.128Skamil#if !TEST_LWP_ENABLED 54691.120Skamil if (trace_create || trace_exit) 54701.119Skamil atf_tc_skip("PR kern/51995"); 54711.128Skamil#endif 54721.1Skamil 54731.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 54741.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 54751.1Skamil if (child == 0) { 54761.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 54771.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 54781.1Skamil 54791.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 54801.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 54811.1Skamil 54821.83Skamil for (n = 0; n < __arraycount(t); n++) { 54831.83Skamil rv = pthread_create(&t[n], NULL, trace_threads_cb, 54841.83Skamil NULL); 54851.83Skamil FORKEE_ASSERT(rv == 0); 54861.83Skamil } 54871.1Skamil 54881.83Skamil for (n = 0; n < __arraycount(t); n++) { 54891.83Skamil rv = pthread_join(t[n], NULL); 54901.83Skamil FORKEE_ASSERT(rv == 0); 54911.83Skamil } 54921.1Skamil 54931.83Skamil /* 54941.83Skamil * There is race between _exit() and pthread_join() detaching 54951.83Skamil * a thread. For simplicity kill the process after detecting 54961.83Skamil * LWP events. 54971.83Skamil */ 54981.83Skamil while (true) 54991.83Skamil continue; 55001.1Skamil 55011.83Skamil FORKEE_ASSERT(0 && "Not reached"); 55021.1Skamil } 55031.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 55041.1Skamil 55051.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 55061.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 55071.1Skamil 55081.1Skamil validate_status_stopped(status, sigval); 55091.1Skamil 55101.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 55111.83Skamil SYSCALL_REQUIRE( 55121.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55131.1Skamil 55141.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55151.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 55161.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55171.83Skamil info.psi_siginfo.si_errno); 55181.1Skamil 55191.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 55201.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 55211.1Skamil 55221.83Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 55231.83Skamil memset(&event, 0, sizeof(event)); 55241.83Skamil if (trace_create) 55251.83Skamil event.pe_set_event |= PTRACE_LWP_CREATE; 55261.83Skamil if (trace_exit) 55271.83Skamil event.pe_set_event |= PTRACE_LWP_EXIT; 55281.83Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 55291.1Skamil 55301.13Schristos DPRINTF("Before resuming the child process where it left off and " 55311.1Skamil "without signal to be sent\n"); 55321.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 55331.1Skamil 55341.83Skamil memset(traced_lwps, 0, sizeof(traced_lwps)); 55351.1Skamil 55361.83Skamil for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) { 55371.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 55381.83Skamil "SIGTRAP\n", TWAIT_FNAME); 55391.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 55401.83Skamil child); 55411.1Skamil 55421.83Skamil validate_status_stopped(status, SIGTRAP); 55431.1Skamil 55441.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 55451.83Skamil "child\n"); 55461.83Skamil SYSCALL_REQUIRE( 55471.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55481.1Skamil 55491.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55501.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 55511.83Skamil "si_errno=%#x\n", 55521.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55531.83Skamil info.psi_siginfo.si_errno); 55541.1Skamil 55551.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 55561.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 55571.1Skamil 55581.83Skamil SYSCALL_REQUIRE( 55591.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 55601.1Skamil 55611.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 55621.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 55631.1Skamil 55641.83Skamil lid = state.pe_lwp; 55651.83Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 55661.1Skamil 55671.83Skamil traced_lwps[lid - 1] = true; 55681.1Skamil 55691.83Skamil DPRINTF("Before resuming the child process where it left off " 55701.83Skamil "and without signal to be sent\n"); 55711.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 55721.83Skamil } 55731.1Skamil 55741.83Skamil for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) { 55751.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 55761.83Skamil "SIGTRAP\n", TWAIT_FNAME); 55771.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 55781.83Skamil child); 55791.1Skamil 55801.83Skamil validate_status_stopped(status, SIGTRAP); 55811.1Skamil 55821.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 55831.83Skamil "child\n"); 55841.83Skamil SYSCALL_REQUIRE( 55851.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55861.1Skamil 55871.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55881.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 55891.83Skamil "si_errno=%#x\n", 55901.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55911.83Skamil info.psi_siginfo.si_errno); 55921.1Skamil 55931.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 55941.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 55951.1Skamil 55961.83Skamil SYSCALL_REQUIRE( 55971.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 55981.1Skamil 55991.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 56001.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 56011.1Skamil 56021.83Skamil lid = state.pe_lwp; 56031.83Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 56041.1Skamil 56051.83Skamil if (trace_create) { 56061.83Skamil ATF_REQUIRE(traced_lwps[lid - 1] == true); 56071.83Skamil traced_lwps[lid - 1] = false; 56081.83Skamil } 56091.1Skamil 56101.83Skamil DPRINTF("Before resuming the child process where it left off " 56111.83Skamil "and without signal to be sent\n"); 56121.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56131.83Skamil } 56141.1Skamil 56151.83Skamil kill(child, SIGKILL); 56161.1Skamil 56171.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 56181.1Skamil TWAIT_FNAME); 56191.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56201.1Skamil 56211.83Skamil validate_status_signaled(status, SIGKILL, 0); 56221.1Skamil 56231.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 56241.1Skamil TWAIT_FNAME); 56251.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 56261.1Skamil} 56271.1Skamil 56281.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit) \ 56291.83SkamilATF_TC(test); \ 56301.83SkamilATF_TC_HEAD(test, tc) \ 56311.83Skamil{ \ 56321.83Skamil atf_tc_set_md_var(tc, "descr", \ 56331.83Skamil "Verify spawning threads with%s tracing LWP create and" \ 56341.83Skamil "with%s tracing LWP exit", trace_create ? "" : "out", \ 56351.83Skamil trace_exit ? "" : "out"); \ 56361.83Skamil} \ 56371.83Skamil \ 56381.83SkamilATF_TC_BODY(test, tc) \ 56391.83Skamil{ \ 56401.83Skamil \ 56411.83Skamil trace_threads(trace_create, trace_exit); \ 56421.83Skamil} 56431.83Skamil 56441.119SkamilTRACE_THREADS(trace_thread_nolwpevents, false, false) 56451.119SkamilTRACE_THREADS(trace_thread_lwpexit, false, true) 56461.119SkamilTRACE_THREADS(trace_thread_lwpcreate, true, false) 56471.119SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true) 56481.83Skamil 56491.83Skamil/// ---------------------------------------------------------------------------- 56501.83Skamil 56511.84SkamilATF_TC(signal_mask_unrelated); 56521.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc) 56531.1Skamil{ 56541.1Skamil atf_tc_set_md_var(tc, "descr", 56551.1Skamil "Verify that masking single unrelated signal does not stop tracer " 56561.1Skamil "from catching other signals"); 56571.1Skamil} 56581.1Skamil 56591.84SkamilATF_TC_BODY(signal_mask_unrelated, tc) 56601.1Skamil{ 56611.1Skamil const int exitval = 5; 56621.1Skamil const int sigval = SIGSTOP; 56631.1Skamil const int sigmasked = SIGTRAP; 56641.1Skamil const int signotmasked = SIGINT; 56651.1Skamil pid_t child, wpid; 56661.1Skamil#if defined(TWAIT_HAVE_STATUS) 56671.1Skamil int status; 56681.1Skamil#endif 56691.1Skamil sigset_t intmask; 56701.1Skamil 56711.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 56721.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 56731.1Skamil if (child == 0) { 56741.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 56751.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 56761.1Skamil 56771.1Skamil sigemptyset(&intmask); 56781.1Skamil sigaddset(&intmask, sigmasked); 56791.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 56801.1Skamil 56811.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 56821.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 56831.1Skamil 56841.13Schristos DPRINTF("Before raising %s from child\n", 56851.1Skamil strsignal(signotmasked)); 56861.1Skamil FORKEE_ASSERT(raise(signotmasked) == 0); 56871.1Skamil 56881.13Schristos DPRINTF("Before exiting of the child process\n"); 56891.1Skamil _exit(exitval); 56901.1Skamil } 56911.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 56921.1Skamil 56931.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56941.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56951.1Skamil 56961.1Skamil validate_status_stopped(status, sigval); 56971.1Skamil 56981.13Schristos DPRINTF("Before resuming the child process where it left off and " 56991.1Skamil "without signal to be sent\n"); 57001.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 57011.1Skamil 57021.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57031.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57041.1Skamil 57051.1Skamil validate_status_stopped(status, signotmasked); 57061.1Skamil 57071.13Schristos DPRINTF("Before resuming the child process where it left off and " 57081.1Skamil "without signal to be sent\n"); 57091.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 57101.1Skamil 57111.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57121.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57131.1Skamil 57141.1Skamil validate_status_exited(status, exitval); 57151.1Skamil 57161.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57171.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 57181.1Skamil} 57191.1Skamil 57201.84Skamil/// ---------------------------------------------------------------------------- 57211.84Skamil 57221.1Skamil#if defined(TWAIT_HAVE_PID) 57231.99Skamilstatic void 57241.126Skamilfork2_body(const char *fn, bool masked, bool ignored) 57251.1Skamil{ 57261.1Skamil const int exitval = 5; 57271.126Skamil const int exitval2 = 0; /* Match exit status from /bin/echo */ 57281.1Skamil const int sigval = SIGSTOP; 57291.99Skamil pid_t child, child2 = 0, wpid; 57301.1Skamil#if defined(TWAIT_HAVE_STATUS) 57311.1Skamil int status; 57321.1Skamil#endif 57331.1Skamil ptrace_state_t state; 57341.1Skamil const int slen = sizeof(state); 57351.1Skamil ptrace_event_t event; 57361.1Skamil const int elen = sizeof(event); 57371.99Skamil struct sigaction sa; 57381.99Skamil struct ptrace_siginfo info; 57391.99Skamil sigset_t intmask; 57401.99Skamil struct kinfo_proc2 kp; 57411.99Skamil size_t len = sizeof(kp); 57421.99Skamil 57431.99Skamil int name[6]; 57441.99Skamil const size_t namelen = __arraycount(name); 57451.99Skamil ki_sigset_t kp_sigmask; 57461.99Skamil ki_sigset_t kp_sigignore; 57471.1Skamil 57481.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 57491.14Schristos 57501.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 57511.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 57521.1Skamil if (child == 0) { 57531.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 57541.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 57551.1Skamil 57561.99Skamil if (masked) { 57571.99Skamil sigemptyset(&intmask); 57581.99Skamil sigaddset(&intmask, SIGTRAP); 57591.99Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 57601.99Skamil } 57611.99Skamil 57621.99Skamil if (ignored) { 57631.99Skamil memset(&sa, 0, sizeof(sa)); 57641.99Skamil sa.sa_handler = SIG_IGN; 57651.99Skamil sigemptyset(&sa.sa_mask); 57661.99Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 57671.99Skamil } 57681.1Skamil 57691.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 57701.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 57711.1Skamil 57721.126Skamil if (strcmp(fn, "spawn") == 0) { 57731.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 57741.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 57751.126Skamil } else { 57761.126Skamil if (strcmp(fn, "fork") == 0) { 57771.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 57781.126Skamil } else { 57791.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 57801.126Skamil } 57811.126Skamil if (child2 == 0) 57821.126Skamil _exit(exitval2); 57831.126Skamil } 57841.1Skamil 57851.1Skamil FORKEE_REQUIRE_SUCCESS 57861.99Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 57871.1Skamil 57881.1Skamil forkee_status_exited(status, exitval2); 57891.1Skamil 57901.13Schristos DPRINTF("Before exiting of the child process\n"); 57911.1Skamil _exit(exitval); 57921.1Skamil } 57931.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 57941.1Skamil 57951.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57961.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57971.1Skamil 57981.1Skamil validate_status_stopped(status, sigval); 57991.1Skamil 58001.99Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 58011.99Skamil SYSCALL_REQUIRE( 58021.99Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 58031.99Skamil 58041.99Skamil DPRINTF("Before checking siginfo_t\n"); 58051.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 58061.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 58071.1Skamil 58081.99Skamil name[0] = CTL_KERN, 58091.99Skamil name[1] = KERN_PROC2, 58101.99Skamil name[2] = KERN_PROC_PID; 58111.99Skamil name[3] = child; 58121.99Skamil name[4] = sizeof(kp); 58131.99Skamil name[5] = 1; 58141.1Skamil 58151.99Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 58161.1Skamil 58171.99Skamil if (masked) 58181.99Skamil kp_sigmask = kp.p_sigmask; 58191.1Skamil 58201.99Skamil if (ignored) 58211.99Skamil kp_sigignore = kp.p_sigignore; 58221.1Skamil 58231.126Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 58241.126Skamil strcmp(fn, "spawn") == 0 ? "|PTRACE_POSIX_SPAWN" : "", 58251.126Skamil strcmp(fn, "fork") == 0 ? "|PTRACE_FORK" : "", 58261.126Skamil strcmp(fn, "vfork") == 0 ? "|PTRACE_VFORK" : "", 58271.126Skamil strcmp(fn, "vforkdone") == 0 ? "|PTRACE_VFORK_DONE" : "", child); 58281.99Skamil event.pe_set_event = 0; 58291.126Skamil if (strcmp(fn, "spawn") == 0) 58301.126Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 58311.126Skamil if (strcmp(fn, "fork") == 0) 58321.99Skamil event.pe_set_event |= PTRACE_FORK; 58331.126Skamil if (strcmp(fn, "vfork") == 0) 58341.99Skamil event.pe_set_event |= PTRACE_VFORK; 58351.126Skamil if (strcmp(fn, "vforkdone") == 0) 58361.99Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 58371.99Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 58381.1Skamil 58391.99Skamil DPRINTF("Before resuming the child process where it left off and " 58401.99Skamil "without signal to be sent\n"); 58411.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 58421.1Skamil 58431.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 58441.126Skamil strcmp(fn, "vfork") == 0) { 58451.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 58461.99Skamil child); 58471.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 58481.99Skamil child); 58491.1Skamil 58501.99Skamil validate_status_stopped(status, SIGTRAP); 58511.1Skamil 58521.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 58531.1Skamil 58541.99Skamil if (masked) { 58551.99Skamil DPRINTF("kp_sigmask=" 58561.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58571.99Skamil PRIx32 "\n", 58581.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 58591.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 58601.1Skamil 58611.99Skamil DPRINTF("kp.p_sigmask=" 58621.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58631.99Skamil PRIx32 "\n", 58641.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 58651.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 58661.1Skamil 58671.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 58681.99Skamil sizeof(kp_sigmask))); 58691.99Skamil } 58701.1Skamil 58711.99Skamil if (ignored) { 58721.99Skamil DPRINTF("kp_sigignore=" 58731.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58741.99Skamil PRIx32 "\n", 58751.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 58761.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 58771.1Skamil 58781.99Skamil DPRINTF("kp.p_sigignore=" 58791.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58801.99Skamil PRIx32 "\n", 58811.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 58821.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 58831.1Skamil 58841.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 58851.99Skamil sizeof(kp_sigignore))); 58861.99Skamil } 58871.1Skamil 58881.99Skamil SYSCALL_REQUIRE( 58891.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 58901.126Skamil if (strcmp(fn, "spawn") == 0) { 58911.126Skamil ATF_REQUIRE_EQ( 58921.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 58931.126Skamil PTRACE_POSIX_SPAWN); 58941.126Skamil } 58951.126Skamil if (strcmp(fn, "fork") == 0) { 58961.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 58971.99Skamil PTRACE_FORK); 58981.99Skamil } 58991.126Skamil if (strcmp(fn, "vfork") == 0) { 59001.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 59011.99Skamil PTRACE_VFORK); 59021.99Skamil } 59031.1Skamil 59041.99Skamil child2 = state.pe_other_pid; 59051.99Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 59061.1Skamil 59071.99Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 59081.99Skamil "%d\n", TWAIT_FNAME, child2, child); 59091.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 59101.99Skamil child2); 59111.1Skamil 59121.99Skamil validate_status_stopped(status, SIGTRAP); 59131.1Skamil 59141.99Skamil name[3] = child2; 59151.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 59161.1Skamil 59171.99Skamil if (masked) { 59181.99Skamil DPRINTF("kp_sigmask=" 59191.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59201.99Skamil PRIx32 "\n", 59211.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 59221.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 59231.1Skamil 59241.99Skamil DPRINTF("kp.p_sigmask=" 59251.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59261.99Skamil PRIx32 "\n", 59271.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 59281.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 59291.14Schristos 59301.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 59311.99Skamil sizeof(kp_sigmask))); 59321.99Skamil } 59331.1Skamil 59341.99Skamil if (ignored) { 59351.99Skamil DPRINTF("kp_sigignore=" 59361.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59371.99Skamil PRIx32 "\n", 59381.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 59391.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 59401.1Skamil 59411.99Skamil DPRINTF("kp.p_sigignore=" 59421.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59431.99Skamil PRIx32 "\n", 59441.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 59451.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 59461.1Skamil 59471.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 59481.99Skamil sizeof(kp_sigignore))); 59491.99Skamil } 59501.1Skamil 59511.99Skamil SYSCALL_REQUIRE( 59521.99Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 59531.126Skamil if (strcmp(fn, "spawn") == 0) { 59541.126Skamil ATF_REQUIRE_EQ( 59551.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 59561.126Skamil PTRACE_POSIX_SPAWN); 59571.126Skamil } 59581.126Skamil if (strcmp(fn, "fork") == 0) { 59591.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 59601.99Skamil PTRACE_FORK); 59611.99Skamil } 59621.126Skamil if (strcmp(fn, "vfork") == 0) { 59631.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 59641.99Skamil PTRACE_VFORK); 59651.99Skamil } 59661.1Skamil 59671.99Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 59681.1Skamil 59691.99Skamil DPRINTF("Before resuming the forkee process where it left off " 59701.99Skamil "and without signal to be sent\n"); 59711.99Skamil SYSCALL_REQUIRE( 59721.99Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 59731.1Skamil 59741.99Skamil DPRINTF("Before resuming the child process where it left off " 59751.99Skamil "and without signal to be sent\n"); 59761.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 59771.1Skamil } 59781.1Skamil 59791.126Skamil if (strcmp(fn, "vforkdone") == 0) { 59801.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 59811.99Skamil child); 59821.99Skamil TWAIT_REQUIRE_SUCCESS( 59831.99Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 59841.1Skamil 59851.99Skamil validate_status_stopped(status, SIGTRAP); 59861.1Skamil 59871.99Skamil name[3] = child; 59881.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 59891.1Skamil 59901.102Skamil /* 59911.102Skamil * SIGCHLD is now pending in the signal queue and 59921.102Skamil * the kernel presents it to userland as a masked signal. 59931.102Skamil */ 59941.102Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 59951.102Skamil 59961.99Skamil if (masked) { 59971.99Skamil DPRINTF("kp_sigmask=" 59981.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59991.99Skamil PRIx32 "\n", 60001.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 60011.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 60021.1Skamil 60031.99Skamil DPRINTF("kp.p_sigmask=" 60041.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60051.99Skamil PRIx32 "\n", 60061.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 60071.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 60081.1Skamil 60091.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 60101.99Skamil sizeof(kp_sigmask))); 60111.99Skamil } 60121.1Skamil 60131.99Skamil if (ignored) { 60141.99Skamil DPRINTF("kp_sigignore=" 60151.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60161.99Skamil PRIx32 "\n", 60171.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 60181.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 60191.1Skamil 60201.99Skamil DPRINTF("kp.p_sigignore=" 60211.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60221.99Skamil PRIx32 "\n", 60231.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 60241.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 60251.1Skamil 60261.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 60271.99Skamil sizeof(kp_sigignore))); 60281.99Skamil } 60291.1Skamil 60301.99Skamil SYSCALL_REQUIRE( 60311.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 60321.99Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 60331.1Skamil 60341.99Skamil child2 = state.pe_other_pid; 60351.99Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 60361.99Skamil child2); 60371.1Skamil 60381.99Skamil DPRINTF("Before resuming the child process where it left off " 60391.99Skamil "and without signal to be sent\n"); 60401.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60411.99Skamil } 60421.1Skamil 60431.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 60441.126Skamil strcmp(fn, "vfork") == 0) { 60451.99Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 60461.99Skamil "\n", TWAIT_FNAME); 60471.99Skamil TWAIT_REQUIRE_SUCCESS( 60481.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 60491.1Skamil 60501.99Skamil validate_status_exited(status, exitval2); 60511.1Skamil 60521.99Skamil DPRINTF("Before calling %s() for the forkee - expected no " 60531.99Skamil "process\n", TWAIT_FNAME); 60541.99Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 60551.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 60561.99Skamil } 60571.1Skamil 60581.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 60591.1Skamil "SIGCHLD\n", TWAIT_FNAME); 60601.57Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60611.1Skamil 60621.1Skamil validate_status_stopped(status, SIGCHLD); 60631.1Skamil 60641.57Skamil 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 exited\n", 60691.1Skamil TWAIT_FNAME); 60701.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60711.1Skamil 60721.1Skamil validate_status_exited(status, exitval); 60731.1Skamil 60741.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 60751.57Skamil TWAIT_FNAME); 60761.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 60771.1Skamil} 60781.1Skamil 60791.126Skamil#define FORK2_TEST(name,fn,masked,ignored) \ 60801.99SkamilATF_TC(name); \ 60811.99SkamilATF_TC_HEAD(name, tc) \ 60821.99Skamil{ \ 60831.126Skamil atf_tc_set_md_var(tc, "descr", "Verify that " fn " is caught " \ 60841.99Skamil "regardless of signal %s%s", \ 60851.99Skamil masked ? "masked" : "", ignored ? "ignored" : ""); \ 60861.99Skamil} \ 60871.99Skamil \ 60881.99SkamilATF_TC_BODY(name, tc) \ 60891.99Skamil{ \ 60901.99Skamil \ 60911.126Skamil fork2_body(fn, masked, ignored); \ 60921.1Skamil} 60931.1Skamil 60941.126SkamilFORK2_TEST(posix_spawn_singalmasked, "spawn", true, false) 60951.126SkamilFORK2_TEST(posix_spawn_singalignored, "spawn", false, true) 60961.126SkamilFORK2_TEST(fork_singalmasked, "fork", true, false) 60971.126SkamilFORK2_TEST(fork_singalignored, "fork", false, true) 60981.110Skamil#if TEST_VFORK_ENABLED 60991.126SkamilFORK2_TEST(vfork_singalmasked, "vfork", true, false) 61001.126SkamilFORK2_TEST(vfork_singalignored, "vfork", false, true) 61011.126SkamilFORK2_TEST(vforkdone_singalmasked, "vforkdone", true, false) 61021.126SkamilFORK2_TEST(vforkdone_singalignored, "vforkdone", false, true) 61031.1Skamil#endif 61041.110Skamil#endif 61051.1Skamil 61061.99Skamil/// ---------------------------------------------------------------------------- 61071.1Skamil 61081.83Skamilvolatile lwpid_t the_lwp_id = 0; 61091.83Skamil 61101.83Skamilstatic void 61111.83Skamillwp_main_func(void *arg) 61121.83Skamil{ 61131.83Skamil the_lwp_id = _lwp_self(); 61141.83Skamil _lwp_exit(); 61151.83Skamil} 61161.83Skamil 61171.1SkamilATF_TC(signal9); 61181.1SkamilATF_TC_HEAD(signal9, tc) 61191.1Skamil{ 61201.1Skamil atf_tc_set_md_var(tc, "descr", 61211.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 61221.1Skamil "catching PTRACE_LWP_CREATE breakpoint"); 61231.1Skamil} 61241.1Skamil 61251.1SkamilATF_TC_BODY(signal9, tc) 61261.1Skamil{ 61271.1Skamil const int exitval = 5; 61281.1Skamil const int sigval = SIGSTOP; 61291.1Skamil const int sigmasked = SIGTRAP; 61301.1Skamil pid_t child, wpid; 61311.1Skamil#if defined(TWAIT_HAVE_STATUS) 61321.1Skamil int status; 61331.1Skamil#endif 61341.1Skamil sigset_t intmask; 61351.1Skamil ptrace_state_t state; 61361.1Skamil const int slen = sizeof(state); 61371.1Skamil ptrace_event_t event; 61381.1Skamil const int elen = sizeof(event); 61391.1Skamil ucontext_t uc; 61401.1Skamil lwpid_t lid; 61411.1Skamil static const size_t ssize = 16*1024; 61421.1Skamil void *stack; 61431.1Skamil 61441.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 61451.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 61461.1Skamil if (child == 0) { 61471.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 61481.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 61491.1Skamil 61501.1Skamil sigemptyset(&intmask); 61511.1Skamil sigaddset(&intmask, sigmasked); 61521.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 61531.1Skamil 61541.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 61551.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 61561.1Skamil 61571.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 61581.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 61591.1Skamil 61601.13Schristos DPRINTF("Before making context for new lwp in child\n"); 61611.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 61621.1Skamil 61631.13Schristos DPRINTF("Before creating new in child\n"); 61641.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 61651.1Skamil 61661.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 61671.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 61681.1Skamil 61691.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 61701.1Skamil "are the same\n", lid, the_lwp_id); 61711.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 61721.1Skamil 61731.13Schristos DPRINTF("Before exiting of the child process\n"); 61741.1Skamil _exit(exitval); 61751.1Skamil } 61761.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 61771.1Skamil 61781.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 61791.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61801.1Skamil 61811.1Skamil validate_status_stopped(status, sigval); 61821.1Skamil 61831.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 61841.1Skamil event.pe_set_event = PTRACE_LWP_CREATE; 61851.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 61861.1Skamil 61871.13Schristos DPRINTF("Before resuming the child process where it left off and " 61881.1Skamil "without signal to be sent\n"); 61891.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 61901.1Skamil 61911.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 61921.1Skamil "SIGTRAP\n", TWAIT_FNAME); 61931.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61941.1Skamil 61951.1Skamil validate_status_stopped(status, sigmasked); 61961.1Skamil 61971.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 61981.1Skamil 61991.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE); 62001.1Skamil 62011.1Skamil lid = state.pe_lwp; 62021.13Schristos DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 62031.1Skamil 62041.13Schristos DPRINTF("Before resuming the child process where it left off and " 62051.1Skamil "without signal to be sent\n"); 62061.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 62071.1Skamil 62081.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 62091.1Skamil TWAIT_FNAME); 62101.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62111.1Skamil 62121.1Skamil validate_status_exited(status, exitval); 62131.1Skamil 62141.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 62151.1Skamil TWAIT_FNAME); 62161.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 62171.1Skamil} 62181.1Skamil 62191.1SkamilATF_TC(signal10); 62201.1SkamilATF_TC_HEAD(signal10, tc) 62211.1Skamil{ 62221.1Skamil atf_tc_set_md_var(tc, "descr", 62231.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 62241.1Skamil "catching PTRACE_LWP_EXIT breakpoint"); 62251.1Skamil} 62261.1Skamil 62271.1SkamilATF_TC_BODY(signal10, tc) 62281.1Skamil{ 62291.1Skamil const int exitval = 5; 62301.1Skamil const int sigval = SIGSTOP; 62311.1Skamil const int sigmasked = SIGTRAP; 62321.1Skamil pid_t child, wpid; 62331.1Skamil#if defined(TWAIT_HAVE_STATUS) 62341.1Skamil int status; 62351.1Skamil#endif 62361.1Skamil sigset_t intmask; 62371.1Skamil ptrace_state_t state; 62381.1Skamil const int slen = sizeof(state); 62391.1Skamil ptrace_event_t event; 62401.1Skamil const int elen = sizeof(event); 62411.1Skamil ucontext_t uc; 62421.1Skamil lwpid_t lid; 62431.1Skamil static const size_t ssize = 16*1024; 62441.1Skamil void *stack; 62451.1Skamil 62461.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 62471.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 62481.1Skamil if (child == 0) { 62491.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 62501.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 62511.1Skamil 62521.1Skamil sigemptyset(&intmask); 62531.1Skamil sigaddset(&intmask, sigmasked); 62541.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 62551.1Skamil 62561.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 62571.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 62581.1Skamil 62591.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 62601.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 62611.1Skamil 62621.13Schristos DPRINTF("Before making context for new lwp in child\n"); 62631.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 62641.1Skamil 62651.13Schristos DPRINTF("Before creating new in child\n"); 62661.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 62671.1Skamil 62681.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 62691.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 62701.1Skamil 62711.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 62721.1Skamil "are the same\n", lid, the_lwp_id); 62731.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 62741.1Skamil 62751.13Schristos DPRINTF("Before exiting of the child process\n"); 62761.1Skamil _exit(exitval); 62771.1Skamil } 62781.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 62791.1Skamil 62801.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 62811.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62821.1Skamil 62831.1Skamil validate_status_stopped(status, sigval); 62841.1Skamil 62851.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 62861.1Skamil event.pe_set_event = PTRACE_LWP_EXIT; 62871.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 62881.1Skamil 62891.13Schristos DPRINTF("Before resuming the child process where it left off and " 62901.1Skamil "without signal to be sent\n"); 62911.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 62921.1Skamil 62931.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 62941.1Skamil "SIGTRAP\n", TWAIT_FNAME); 62951.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62961.1Skamil 62971.1Skamil validate_status_stopped(status, sigmasked); 62981.1Skamil 62991.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 63001.1Skamil 63011.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT); 63021.1Skamil 63031.1Skamil lid = state.pe_lwp; 63041.13Schristos DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 63051.1Skamil 63061.13Schristos DPRINTF("Before resuming the child process where it left off and " 63071.1Skamil "without signal to be sent\n"); 63081.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63091.1Skamil 63101.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 63111.1Skamil TWAIT_FNAME); 63121.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63131.1Skamil 63141.1Skamil validate_status_exited(status, exitval); 63151.1Skamil 63161.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 63171.1Skamil TWAIT_FNAME); 63181.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 63191.1Skamil} 63201.1Skamil 63211.1Skamilstatic void 63221.1Skamillwp_main_stop(void *arg) 63231.1Skamil{ 63241.1Skamil the_lwp_id = _lwp_self(); 63251.1Skamil 63261.1Skamil raise(SIGTRAP); 63271.1Skamil 63281.1Skamil _lwp_exit(); 63291.1Skamil} 63301.1Skamil 63311.1SkamilATF_TC(suspend1); 63321.1SkamilATF_TC_HEAD(suspend1, tc) 63331.1Skamil{ 63341.1Skamil atf_tc_set_md_var(tc, "descr", 63351.1Skamil "Verify that a thread can be suspended by a debugger and later " 63361.1Skamil "resumed by a tracee"); 63371.1Skamil} 63381.1Skamil 63391.1SkamilATF_TC_BODY(suspend1, tc) 63401.1Skamil{ 63411.1Skamil const int exitval = 5; 63421.1Skamil const int sigval = SIGSTOP; 63431.1Skamil pid_t child, wpid; 63441.1Skamil#if defined(TWAIT_HAVE_STATUS) 63451.1Skamil int status; 63461.1Skamil#endif 63471.1Skamil ucontext_t uc; 63481.1Skamil lwpid_t lid; 63491.1Skamil static const size_t ssize = 16*1024; 63501.1Skamil void *stack; 63511.1Skamil struct ptrace_lwpinfo pl; 63521.1Skamil struct ptrace_siginfo psi; 63531.1Skamil volatile int go = 0; 63541.1Skamil 63551.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 63561.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 63571.1Skamil if (child == 0) { 63581.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 63591.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 63601.1Skamil 63611.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 63621.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 63631.1Skamil 63641.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 63651.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 63661.1Skamil 63671.13Schristos DPRINTF("Before making context for new lwp in child\n"); 63681.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 63691.1Skamil 63701.13Schristos DPRINTF("Before creating new in child\n"); 63711.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 63721.1Skamil 63731.1Skamil while (go == 0) 63741.1Skamil continue; 63751.1Skamil 63761.1Skamil raise(SIGINT); 63771.1Skamil 63781.1Skamil FORKEE_ASSERT(_lwp_continue(lid) == 0); 63791.1Skamil 63801.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 63811.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 63821.1Skamil 63831.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 63841.1Skamil "are the same\n", lid, the_lwp_id); 63851.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 63861.1Skamil 63871.13Schristos DPRINTF("Before exiting of the child process\n"); 63881.1Skamil _exit(exitval); 63891.1Skamil } 63901.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 63911.1Skamil 63921.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 63931.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63941.1Skamil 63951.1Skamil validate_status_stopped(status, sigval); 63961.1Skamil 63971.13Schristos DPRINTF("Before resuming the child process where it left off and " 63981.1Skamil "without signal to be sent\n"); 63991.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64001.1Skamil 64011.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 64021.1Skamil "SIGTRAP\n", TWAIT_FNAME); 64031.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64041.1Skamil 64051.1Skamil validate_status_stopped(status, SIGTRAP); 64061.1Skamil 64071.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 64081.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 64091.1Skamil 64101.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 64111.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 64121.1Skamil 64131.13Schristos DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n", 64141.1Skamil child, getpid()); 64151.13Schristos SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1); 64161.1Skamil 64171.13Schristos DPRINTF("Before resuming the child process where it left off and " 64181.1Skamil "without signal to be sent\n"); 64191.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64201.1Skamil 64211.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 64221.1Skamil "SIGINT\n", TWAIT_FNAME); 64231.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64241.1Skamil 64251.1Skamil validate_status_stopped(status, SIGINT); 64261.1Skamil 64271.1Skamil pl.pl_lwpid = 0; 64281.1Skamil 64291.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 64301.1Skamil while (pl.pl_lwpid != 0) { 64311.1Skamil 64321.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 64331.1Skamil switch (pl.pl_lwpid) { 64341.1Skamil case 1: 64351.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 64361.1Skamil break; 64371.1Skamil case 2: 64381.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 64391.1Skamil break; 64401.1Skamil } 64411.1Skamil } 64421.1Skamil 64431.13Schristos DPRINTF("Before resuming the child process where it left off and " 64441.1Skamil "without signal to be sent\n"); 64451.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64461.1Skamil 64471.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 64481.1Skamil TWAIT_FNAME); 64491.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64501.1Skamil 64511.1Skamil validate_status_exited(status, exitval); 64521.1Skamil 64531.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 64541.1Skamil TWAIT_FNAME); 64551.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 64561.1Skamil} 64571.1Skamil 64581.1SkamilATF_TC(suspend2); 64591.1SkamilATF_TC_HEAD(suspend2, tc) 64601.1Skamil{ 64611.1Skamil atf_tc_set_md_var(tc, "descr", 64621.1Skamil "Verify that the while the only thread within a process is " 64631.1Skamil "suspended, the whole process cannot be unstopped"); 64641.1Skamil} 64651.1Skamil 64661.1SkamilATF_TC_BODY(suspend2, tc) 64671.1Skamil{ 64681.1Skamil const int exitval = 5; 64691.1Skamil const int sigval = SIGSTOP; 64701.1Skamil pid_t child, wpid; 64711.1Skamil#if defined(TWAIT_HAVE_STATUS) 64721.1Skamil int status; 64731.1Skamil#endif 64741.1Skamil struct ptrace_siginfo psi; 64751.1Skamil 64761.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 64771.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 64781.1Skamil if (child == 0) { 64791.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 64801.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 64811.1Skamil 64821.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 64831.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 64841.1Skamil 64851.13Schristos DPRINTF("Before exiting of the child process\n"); 64861.1Skamil _exit(exitval); 64871.1Skamil } 64881.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 64891.1Skamil 64901.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 64911.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64921.1Skamil 64931.1Skamil validate_status_stopped(status, sigval); 64941.1Skamil 64951.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 64961.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 64971.1Skamil 64981.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 64991.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 65001.1Skamil 65011.13Schristos DPRINTF("Before resuming the child process where it left off and " 65021.1Skamil "without signal to be sent\n"); 65031.1Skamil ATF_REQUIRE_ERRNO(EDEADLK, 65041.1Skamil ptrace(PT_CONTINUE, child, (void *)1, 0) == -1); 65051.1Skamil 65061.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 65071.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 65081.1Skamil 65091.13Schristos DPRINTF("Before resuming the child process where it left off and " 65101.1Skamil "without signal to be sent\n"); 65111.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65121.1Skamil 65131.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 65141.1Skamil TWAIT_FNAME); 65151.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65161.1Skamil 65171.1Skamil validate_status_exited(status, exitval); 65181.1Skamil 65191.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 65201.1Skamil TWAIT_FNAME); 65211.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 65221.1Skamil} 65231.1Skamil 65241.1SkamilATF_TC(resume1); 65251.1SkamilATF_TC_HEAD(resume1, tc) 65261.1Skamil{ 65271.1Skamil atf_tc_set_md_var(tc, "descr", 65281.1Skamil "Verify that a thread can be suspended by a debugger and later " 65291.1Skamil "resumed by the debugger"); 65301.1Skamil} 65311.1Skamil 65321.1SkamilATF_TC_BODY(resume1, tc) 65331.1Skamil{ 65341.1Skamil struct msg_fds fds; 65351.1Skamil const int exitval = 5; 65361.1Skamil const int sigval = SIGSTOP; 65371.1Skamil pid_t child, wpid; 65381.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 65391.1Skamil#if defined(TWAIT_HAVE_STATUS) 65401.1Skamil int status; 65411.1Skamil#endif 65421.1Skamil ucontext_t uc; 65431.1Skamil lwpid_t lid; 65441.1Skamil static const size_t ssize = 16*1024; 65451.1Skamil void *stack; 65461.1Skamil struct ptrace_lwpinfo pl; 65471.1Skamil struct ptrace_siginfo psi; 65481.1Skamil 65491.13Schristos SYSCALL_REQUIRE(msg_open(&fds) == 0); 65501.1Skamil 65511.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 65521.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 65531.1Skamil if (child == 0) { 65541.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 65551.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 65561.1Skamil 65571.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 65581.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 65591.1Skamil 65601.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 65611.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 65621.1Skamil 65631.13Schristos DPRINTF("Before making context for new lwp in child\n"); 65641.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 65651.1Skamil 65661.13Schristos DPRINTF("Before creating new in child\n"); 65671.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 65681.1Skamil 65691.1Skamil CHILD_TO_PARENT("Message", fds, msg); 65701.1Skamil 65711.1Skamil raise(SIGINT); 65721.1Skamil 65731.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 65741.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 65751.1Skamil 65761.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 65771.1Skamil "are the same\n", lid, the_lwp_id); 65781.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 65791.1Skamil 65801.13Schristos DPRINTF("Before exiting of the child process\n"); 65811.1Skamil _exit(exitval); 65821.1Skamil } 65831.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 65841.1Skamil 65851.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65861.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65871.1Skamil 65881.1Skamil validate_status_stopped(status, sigval); 65891.1Skamil 65901.13Schristos DPRINTF("Before resuming the child process where it left off and " 65911.1Skamil "without signal to be sent\n"); 65921.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65931.1Skamil 65941.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 65951.1Skamil "SIGTRAP\n", TWAIT_FNAME); 65961.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65971.1Skamil 65981.1Skamil validate_status_stopped(status, SIGTRAP); 65991.1Skamil 66001.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 66011.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 66021.1Skamil 66031.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 66041.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 66051.1Skamil 66061.1Skamil PARENT_FROM_CHILD("Message", fds, msg); 66071.1Skamil 66081.13Schristos DPRINTF("Before resuming the child process where it left off and " 66091.1Skamil "without signal to be sent\n"); 66101.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66111.1Skamil 66121.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 66131.1Skamil "SIGINT\n", TWAIT_FNAME); 66141.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66151.1Skamil 66161.1Skamil validate_status_stopped(status, SIGINT); 66171.1Skamil 66181.1Skamil pl.pl_lwpid = 0; 66191.1Skamil 66201.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 66211.1Skamil while (pl.pl_lwpid != 0) { 66221.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 66231.1Skamil switch (pl.pl_lwpid) { 66241.1Skamil case 1: 66251.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 66261.1Skamil break; 66271.1Skamil case 2: 66281.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 66291.1Skamil break; 66301.1Skamil } 66311.1Skamil } 66321.1Skamil 66331.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 66341.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 66351.1Skamil 66361.13Schristos DPRINTF("Before resuming the child process where it left off and " 66371.1Skamil "without signal to be sent\n"); 66381.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66391.1Skamil 66401.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 66411.1Skamil TWAIT_FNAME); 66421.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66431.1Skamil 66441.1Skamil validate_status_exited(status, exitval); 66451.1Skamil 66461.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 66471.1Skamil TWAIT_FNAME); 66481.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 66491.1Skamil 66501.1Skamil msg_close(&fds); 66511.1Skamil} 66521.1Skamil 66531.1SkamilATF_TC(syscall1); 66541.1SkamilATF_TC_HEAD(syscall1, tc) 66551.1Skamil{ 66561.1Skamil atf_tc_set_md_var(tc, "descr", 66571.1Skamil "Verify that getpid(2) can be traced with PT_SYSCALL"); 66581.1Skamil} 66591.1Skamil 66601.1SkamilATF_TC_BODY(syscall1, tc) 66611.1Skamil{ 66621.1Skamil const int exitval = 5; 66631.1Skamil const int sigval = SIGSTOP; 66641.1Skamil pid_t child, wpid; 66651.1Skamil#if defined(TWAIT_HAVE_STATUS) 66661.1Skamil int status; 66671.1Skamil#endif 66681.1Skamil struct ptrace_siginfo info; 66691.1Skamil memset(&info, 0, sizeof(info)); 66701.1Skamil 66711.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 66721.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 66731.1Skamil if (child == 0) { 66741.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 66751.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 66761.1Skamil 66771.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 66781.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 66791.1Skamil 66801.1Skamil syscall(SYS_getpid); 66811.1Skamil 66821.13Schristos DPRINTF("Before exiting of the child process\n"); 66831.1Skamil _exit(exitval); 66841.1Skamil } 66851.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 66861.1Skamil 66871.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66881.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66891.1Skamil 66901.1Skamil validate_status_stopped(status, sigval); 66911.1Skamil 66921.13Schristos DPRINTF("Before resuming the child process where it left off and " 66931.1Skamil "without signal to be sent\n"); 66941.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 66951.1Skamil 66961.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66971.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66981.1Skamil 66991.1Skamil validate_status_stopped(status, SIGTRAP); 67001.1Skamil 67011.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 67021.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 67031.1Skamil 67041.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 67051.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 67061.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 67071.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE); 67081.1Skamil 67091.13Schristos DPRINTF("Before resuming the child process where it left off and " 67101.1Skamil "without signal to be sent\n"); 67111.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 67121.1Skamil 67131.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67141.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67151.1Skamil 67161.1Skamil validate_status_stopped(status, SIGTRAP); 67171.1Skamil 67181.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 67191.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 67201.1Skamil 67211.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 67221.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 67231.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 67241.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX); 67251.1Skamil 67261.13Schristos DPRINTF("Before resuming the child process where it left off and " 67271.1Skamil "without signal to be sent\n"); 67281.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 67291.1Skamil 67301.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67311.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67321.1Skamil 67331.1Skamil validate_status_exited(status, exitval); 67341.1Skamil 67351.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67361.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 67371.1Skamil} 67381.1Skamil 67391.1SkamilATF_TC(syscallemu1); 67401.1SkamilATF_TC_HEAD(syscallemu1, tc) 67411.1Skamil{ 67421.1Skamil atf_tc_set_md_var(tc, "descr", 67431.1Skamil "Verify that exit(2) can be intercepted with PT_SYSCALLEMU"); 67441.1Skamil} 67451.1Skamil 67461.1SkamilATF_TC_BODY(syscallemu1, tc) 67471.1Skamil{ 67481.1Skamil const int exitval = 5; 67491.1Skamil const int sigval = SIGSTOP; 67501.1Skamil pid_t child, wpid; 67511.1Skamil#if defined(TWAIT_HAVE_STATUS) 67521.1Skamil int status; 67531.1Skamil#endif 67541.1Skamil 67551.6Skamil#if defined(__sparc__) && !defined(__sparc64__) 67561.6Skamil /* syscallemu does not work on sparc (32-bit) */ 67571.6Skamil atf_tc_expect_fail("PR kern/52166"); 67581.6Skamil#endif 67591.6Skamil 67601.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 67611.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 67621.1Skamil if (child == 0) { 67631.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 67641.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 67651.1Skamil 67661.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 67671.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 67681.1Skamil 67691.1Skamil syscall(SYS_exit, 100); 67701.1Skamil 67711.13Schristos DPRINTF("Before exiting of the child process\n"); 67721.1Skamil _exit(exitval); 67731.1Skamil } 67741.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 67751.1Skamil 67761.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67771.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67781.1Skamil 67791.1Skamil validate_status_stopped(status, sigval); 67801.1Skamil 67811.13Schristos DPRINTF("Before resuming the child process where it left off and " 67821.1Skamil "without signal to be sent\n"); 67831.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 67841.1Skamil 67851.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67861.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67871.1Skamil 67881.1Skamil validate_status_stopped(status, SIGTRAP); 67891.1Skamil 67901.13Schristos DPRINTF("Set SYSCALLEMU for intercepted syscall\n"); 67911.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1); 67921.1Skamil 67931.13Schristos DPRINTF("Before resuming the child process where it left off and " 67941.1Skamil "without signal to be sent\n"); 67951.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 67961.1Skamil 67971.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67981.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67991.1Skamil 68001.1Skamil validate_status_stopped(status, SIGTRAP); 68011.1Skamil 68021.13Schristos DPRINTF("Before resuming the child process where it left off and " 68031.1Skamil "without signal to be sent\n"); 68041.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68051.1Skamil 68061.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 68071.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68081.1Skamil 68091.1Skamil validate_status_exited(status, exitval); 68101.1Skamil 68111.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 68121.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 68131.1Skamil} 68141.1Skamil 68151.103Skamil/// ---------------------------------------------------------------------------- 68161.103Skamil 68171.106Skamilstatic void 68181.106Skamilclone_body(int flags, bool trackfork, bool trackvfork, 68191.106Skamil bool trackvforkdone) 68201.106Skamil{ 68211.106Skamil const int exitval = 5; 68221.106Skamil const int exitval2 = 15; 68231.106Skamil const int sigval = SIGSTOP; 68241.106Skamil pid_t child, child2 = 0, wpid; 68251.106Skamil#if defined(TWAIT_HAVE_STATUS) 68261.106Skamil int status; 68271.106Skamil#endif 68281.106Skamil ptrace_state_t state; 68291.106Skamil const int slen = sizeof(state); 68301.106Skamil ptrace_event_t event; 68311.106Skamil const int elen = sizeof(event); 68321.106Skamil 68331.106Skamil const size_t stack_size = 1024 * 1024; 68341.106Skamil void *stack, *stack_base; 68351.106Skamil 68361.106Skamil stack = malloc(stack_size); 68371.106Skamil ATF_REQUIRE(stack != NULL); 68381.106Skamil 68391.106Skamil#ifdef __MACHINE_STACK_GROWS_UP 68401.106Skamil stack_base = stack; 68411.106Skamil#else 68421.106Skamil stack_base = (char *)stack + stack_size; 68431.106Skamil#endif 68441.106Skamil 68451.106Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 68461.106Skamil SYSCALL_REQUIRE((child = fork()) != -1); 68471.106Skamil if (child == 0) { 68481.106Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 68491.106Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 68501.106Skamil 68511.106Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 68521.106Skamil FORKEE_ASSERT(raise(sigval) == 0); 68531.106Skamil 68541.106Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 68551.106Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 68561.106Skamil 68571.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 68581.106Skamil child2); 68591.106Skamil 68601.106Skamil // XXX WALLSIG? 68611.106Skamil FORKEE_REQUIRE_SUCCESS 68621.106Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 68631.106Skamil 68641.106Skamil forkee_status_exited(status, exitval2); 68651.106Skamil 68661.106Skamil DPRINTF("Before exiting of the child process\n"); 68671.106Skamil _exit(exitval); 68681.106Skamil } 68691.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 68701.106Skamil 68711.106Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 68721.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68731.106Skamil 68741.106Skamil validate_status_stopped(status, sigval); 68751.106Skamil 68761.106Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 68771.106Skamil trackfork ? "|PTRACE_FORK" : "", 68781.106Skamil trackvfork ? "|PTRACE_VFORK" : "", 68791.106Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 68801.106Skamil event.pe_set_event = 0; 68811.106Skamil if (trackfork) 68821.106Skamil event.pe_set_event |= PTRACE_FORK; 68831.106Skamil if (trackvfork) 68841.106Skamil event.pe_set_event |= PTRACE_VFORK; 68851.106Skamil if (trackvforkdone) 68861.106Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 68871.106Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 68881.106Skamil 68891.106Skamil DPRINTF("Before resuming the child process where it left off and " 68901.106Skamil "without signal to be sent\n"); 68911.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68921.106Skamil 68931.106Skamil#if defined(TWAIT_HAVE_PID) 68941.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 68951.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 68961.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 68971.106Skamil child); 68981.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 68991.106Skamil child); 69001.106Skamil 69011.106Skamil validate_status_stopped(status, SIGTRAP); 69021.106Skamil 69031.106Skamil SYSCALL_REQUIRE( 69041.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 69051.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 69061.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 69071.106Skamil PTRACE_FORK); 69081.106Skamil } 69091.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 69101.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 69111.106Skamil PTRACE_VFORK); 69121.106Skamil } 69131.106Skamil 69141.106Skamil child2 = state.pe_other_pid; 69151.106Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 69161.106Skamil 69171.106Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 69181.106Skamil "%d\n", TWAIT_FNAME, child2, child); 69191.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 69201.106Skamil child2); 69211.106Skamil 69221.106Skamil validate_status_stopped(status, SIGTRAP); 69231.106Skamil 69241.106Skamil SYSCALL_REQUIRE( 69251.106Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 69261.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 69271.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 69281.106Skamil PTRACE_FORK); 69291.106Skamil } 69301.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 69311.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 69321.106Skamil PTRACE_VFORK); 69331.106Skamil } 69341.106Skamil 69351.106Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 69361.106Skamil 69371.106Skamil DPRINTF("Before resuming the forkee process where it left off " 69381.106Skamil "and without signal to be sent\n"); 69391.106Skamil SYSCALL_REQUIRE( 69401.106Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 69411.106Skamil 69421.106Skamil DPRINTF("Before resuming the child process where it left off " 69431.106Skamil "and without signal to be sent\n"); 69441.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69451.106Skamil } 69461.106Skamil#endif 69471.106Skamil 69481.106Skamil if (trackvforkdone && (flags & CLONE_VFORK)) { 69491.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 69501.106Skamil child); 69511.106Skamil TWAIT_REQUIRE_SUCCESS( 69521.106Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 69531.106Skamil 69541.106Skamil validate_status_stopped(status, SIGTRAP); 69551.106Skamil 69561.106Skamil SYSCALL_REQUIRE( 69571.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 69581.106Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 69591.106Skamil 69601.106Skamil child2 = state.pe_other_pid; 69611.106Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 69621.106Skamil child2); 69631.106Skamil 69641.106Skamil DPRINTF("Before resuming the child process where it left off " 69651.106Skamil "and without signal to be sent\n"); 69661.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69671.106Skamil } 69681.106Skamil 69691.103Skamil#if defined(TWAIT_HAVE_PID) 69701.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 69711.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 69721.106Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 69731.106Skamil "\n", TWAIT_FNAME); 69741.106Skamil TWAIT_REQUIRE_SUCCESS( 69751.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 69761.106Skamil 69771.106Skamil validate_status_exited(status, exitval2); 69781.106Skamil 69791.106Skamil DPRINTF("Before calling %s() for the forkee - expected no " 69801.106Skamil "process\n", TWAIT_FNAME); 69811.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 69821.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 69831.106Skamil } 69841.106Skamil#endif 69851.106Skamil 69861.106Skamil DPRINTF("Before calling %s() for the child - expected stopped " 69871.106Skamil "SIGCHLD\n", TWAIT_FNAME); 69881.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 69891.106Skamil 69901.106Skamil validate_status_stopped(status, SIGCHLD); 69911.106Skamil 69921.106Skamil DPRINTF("Before resuming the child process where it left off and " 69931.106Skamil "without signal to be sent\n"); 69941.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69951.106Skamil 69961.106Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 69971.106Skamil TWAIT_FNAME); 69981.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 69991.106Skamil 70001.106Skamil validate_status_exited(status, exitval); 70011.103Skamil 70021.106Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 70031.106Skamil TWAIT_FNAME); 70041.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 70051.106Skamil} 70061.103Skamil 70071.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone) \ 70081.106SkamilATF_TC(name); \ 70091.106SkamilATF_TC_HEAD(name, tc) \ 70101.106Skamil{ \ 70111.106Skamil atf_tc_set_md_var(tc, "descr", "Verify clone(%s) " \ 70121.106Skamil "called with 0%s%s%s in EVENT_MASK", \ 70131.106Skamil #flags, \ 70141.106Skamil tfork ? "|PTRACE_FORK" : "", \ 70151.106Skamil tvfork ? "|PTRACE_VFORK" : "", \ 70161.106Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 70171.106Skamil} \ 70181.106Skamil \ 70191.106SkamilATF_TC_BODY(name, tc) \ 70201.106Skamil{ \ 70211.106Skamil \ 70221.106Skamil clone_body(flags, tfork, tvfork, tvforkdone); \ 70231.103Skamil} 70241.103Skamil 70251.106SkamilCLONE_TEST(clone1, 0, false, false, false) 70261.106Skamil#if defined(TWAIT_HAVE_PID) 70271.106SkamilCLONE_TEST(clone2, 0, true, false, false) 70281.106SkamilCLONE_TEST(clone3, 0, false, true, false) 70291.106SkamilCLONE_TEST(clone4, 0, true, true, false) 70301.106Skamil#endif 70311.106SkamilCLONE_TEST(clone5, 0, false, false, true) 70321.106Skamil#if defined(TWAIT_HAVE_PID) 70331.106SkamilCLONE_TEST(clone6, 0, true, false, true) 70341.106SkamilCLONE_TEST(clone7, 0, false, true, true) 70351.106SkamilCLONE_TEST(clone8, 0, true, true, true) 70361.106Skamil#endif 70371.106Skamil 70381.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false) 70391.106Skamil#if defined(TWAIT_HAVE_PID) 70401.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false) 70411.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false) 70421.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false) 70431.106Skamil#endif 70441.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true) 70451.106Skamil#if defined(TWAIT_HAVE_PID) 70461.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true) 70471.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true) 70481.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true) 70491.106Skamil#endif 70501.106Skamil 70511.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false) 70521.106Skamil#if defined(TWAIT_HAVE_PID) 70531.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false) 70541.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false) 70551.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false) 70561.106Skamil#endif 70571.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true) 70581.106Skamil#if defined(TWAIT_HAVE_PID) 70591.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true) 70601.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true) 70611.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true) 70621.106Skamil#endif 70631.106Skamil 70641.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false) 70651.106Skamil#if defined(TWAIT_HAVE_PID) 70661.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false) 70671.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false) 70681.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false) 70691.106Skamil#endif 70701.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true) 70711.106Skamil#if defined(TWAIT_HAVE_PID) 70721.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true) 70731.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true) 70741.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true) 70751.106Skamil#endif 70761.106Skamil 70771.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false) 70781.106Skamil#if defined(TWAIT_HAVE_PID) 70791.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false) 70801.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false) 70811.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false) 70821.106Skamil#endif 70831.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true) 70841.106Skamil#if defined(TWAIT_HAVE_PID) 70851.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true) 70861.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true) 70871.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true) 70881.106Skamil#endif 70891.106Skamil 70901.110Skamil#if TEST_VFORK_ENABLED 70911.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false) 70921.106Skamil#if defined(TWAIT_HAVE_PID) 70931.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false) 70941.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false) 70951.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false) 70961.106Skamil#endif 70971.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true) 70981.106Skamil#if defined(TWAIT_HAVE_PID) 70991.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true) 71001.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true) 71011.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true) 71021.106Skamil#endif 71031.110Skamil#endif 71041.106Skamil 71051.106Skamil/// ---------------------------------------------------------------------------- 71061.106Skamil 71071.106Skamil#if defined(TWAIT_HAVE_PID) 71081.103Skamilstatic void 71091.106Skamilclone_body2(int flags, bool masked, bool ignored) 71101.103Skamil{ 71111.103Skamil const int exitval = 5; 71121.103Skamil const int exitval2 = 15; 71131.103Skamil const int sigval = SIGSTOP; 71141.103Skamil pid_t child, child2 = 0, wpid; 71151.103Skamil#if defined(TWAIT_HAVE_STATUS) 71161.103Skamil int status; 71171.103Skamil#endif 71181.103Skamil ptrace_state_t state; 71191.103Skamil const int slen = sizeof(state); 71201.103Skamil ptrace_event_t event; 71211.103Skamil const int elen = sizeof(event); 71221.103Skamil struct sigaction sa; 71231.103Skamil struct ptrace_siginfo info; 71241.103Skamil sigset_t intmask; 71251.103Skamil struct kinfo_proc2 kp; 71261.103Skamil size_t len = sizeof(kp); 71271.103Skamil 71281.103Skamil int name[6]; 71291.103Skamil const size_t namelen = __arraycount(name); 71301.103Skamil ki_sigset_t kp_sigmask; 71311.103Skamil ki_sigset_t kp_sigignore; 71321.103Skamil 71331.103Skamil const size_t stack_size = 1024 * 1024; 71341.103Skamil void *stack, *stack_base; 71351.103Skamil 71361.103Skamil stack = malloc(stack_size); 71371.103Skamil ATF_REQUIRE(stack != NULL); 71381.103Skamil 71391.103Skamil#ifdef __MACHINE_STACK_GROWS_UP 71401.103Skamil stack_base = stack; 71411.103Skamil#else 71421.103Skamil stack_base = (char *)stack + stack_size; 71431.103Skamil#endif 71441.103Skamil 71451.103Skamil SYSCALL_REQUIRE((child = fork()) != -1); 71461.103Skamil if (child == 0) { 71471.103Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 71481.103Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 71491.103Skamil 71501.103Skamil if (masked) { 71511.103Skamil sigemptyset(&intmask); 71521.103Skamil sigaddset(&intmask, SIGTRAP); 71531.103Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 71541.103Skamil } 71551.103Skamil 71561.103Skamil if (ignored) { 71571.103Skamil memset(&sa, 0, sizeof(sa)); 71581.103Skamil sa.sa_handler = SIG_IGN; 71591.103Skamil sigemptyset(&sa.sa_mask); 71601.103Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 71611.103Skamil } 71621.103Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 71631.103Skamil FORKEE_ASSERT(raise(sigval) == 0); 71641.103Skamil 71651.103Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 71661.103Skamil flags); 71671.103Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 71681.103Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 71691.103Skamil 71701.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 71711.103Skamil child2); 71721.103Skamil 71731.103Skamil // XXX WALLSIG? 71741.103Skamil FORKEE_REQUIRE_SUCCESS 71751.103Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 71761.103Skamil 71771.103Skamil forkee_status_exited(status, exitval2); 71781.103Skamil 71791.103Skamil DPRINTF("Before exiting of the child process\n"); 71801.103Skamil _exit(exitval); 71811.103Skamil } 71821.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 71831.103Skamil 71841.103Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 71851.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 71861.103Skamil 71871.103Skamil validate_status_stopped(status, sigval); 71881.103Skamil 71891.103Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 71901.103Skamil SYSCALL_REQUIRE( 71911.103Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 71921.103Skamil 71931.103Skamil DPRINTF("Before checking siginfo_t\n"); 71941.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 71951.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 71961.103Skamil 71971.103Skamil name[0] = CTL_KERN, 71981.103Skamil name[1] = KERN_PROC2, 71991.103Skamil name[2] = KERN_PROC_PID; 72001.103Skamil name[3] = child; 72011.103Skamil name[4] = sizeof(kp); 72021.103Skamil name[5] = 1; 72031.103Skamil 72041.103Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 72051.103Skamil 72061.103Skamil if (masked) 72071.103Skamil kp_sigmask = kp.p_sigmask; 72081.103Skamil 72091.103Skamil if (ignored) 72101.103Skamil kp_sigignore = kp.p_sigignore; 72111.103Skamil 72121.103Skamil DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in " 72131.103Skamil "EVENT_MASK for the child %d\n", child); 72141.103Skamil event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE; 72151.103Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 72161.103Skamil 72171.103Skamil DPRINTF("Before resuming the child process where it left off and " 72181.103Skamil "without signal to be sent\n"); 72191.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 72201.103Skamil 72211.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 72221.103Skamil child); 72231.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 72241.103Skamil child); 72251.103Skamil 72261.103Skamil validate_status_stopped(status, SIGTRAP); 72271.103Skamil 72281.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 72291.103Skamil 72301.103Skamil if (masked) { 72311.103Skamil DPRINTF("kp_sigmask=" 72321.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72331.103Skamil PRIx32 "\n", 72341.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 72351.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 72361.103Skamil 72371.103Skamil DPRINTF("kp.p_sigmask=" 72381.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72391.103Skamil PRIx32 "\n", 72401.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 72411.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 72421.103Skamil 72431.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 72441.103Skamil sizeof(kp_sigmask))); 72451.103Skamil } 72461.103Skamil 72471.103Skamil if (ignored) { 72481.103Skamil DPRINTF("kp_sigignore=" 72491.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72501.103Skamil PRIx32 "\n", 72511.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 72521.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 72531.103Skamil 72541.103Skamil DPRINTF("kp.p_sigignore=" 72551.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72561.103Skamil PRIx32 "\n", 72571.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 72581.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 72591.103Skamil 72601.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 72611.103Skamil sizeof(kp_sigignore))); 72621.103Skamil } 72631.103Skamil 72641.103Skamil SYSCALL_REQUIRE( 72651.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 72661.103Skamil DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event, 72671.103Skamil child2); 72681.103Skamil if (!(flags & CLONE_VFORK)) { 72691.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 72701.103Skamil PTRACE_FORK); 72711.103Skamil } else { 72721.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 72731.103Skamil PTRACE_VFORK); 72741.103Skamil } 72751.103Skamil 72761.103Skamil child2 = state.pe_other_pid; 72771.103Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 72781.103Skamil 72791.103Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 72801.103Skamil "%d\n", TWAIT_FNAME, child2, child); 72811.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 72821.103Skamil child2); 72831.103Skamil 72841.103Skamil validate_status_stopped(status, SIGTRAP); 72851.103Skamil 72861.103Skamil name[3] = child2; 72871.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 72881.103Skamil 72891.103Skamil if (masked) { 72901.103Skamil DPRINTF("kp_sigmask=" 72911.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72921.103Skamil PRIx32 "\n", 72931.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 72941.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 72951.103Skamil 72961.103Skamil DPRINTF("kp.p_sigmask=" 72971.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72981.103Skamil PRIx32 "\n", 72991.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 73001.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 73011.103Skamil 73021.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 73031.103Skamil sizeof(kp_sigmask))); 73041.103Skamil } 73051.103Skamil 73061.103Skamil if (ignored) { 73071.103Skamil DPRINTF("kp_sigignore=" 73081.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73091.103Skamil PRIx32 "\n", 73101.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 73111.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 73121.103Skamil 73131.103Skamil DPRINTF("kp.p_sigignore=" 73141.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73151.103Skamil PRIx32 "\n", 73161.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 73171.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 73181.103Skamil 73191.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 73201.103Skamil sizeof(kp_sigignore))); 73211.103Skamil } 73221.103Skamil 73231.103Skamil SYSCALL_REQUIRE( 73241.103Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 73251.103Skamil if (!(flags & CLONE_VFORK)) { 73261.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 73271.103Skamil PTRACE_FORK); 73281.103Skamil } else { 73291.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 73301.103Skamil PTRACE_VFORK); 73311.103Skamil } 73321.103Skamil 73331.103Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 73341.103Skamil 73351.103Skamil DPRINTF("Before resuming the forkee process where it left off " 73361.103Skamil "and without signal to be sent\n"); 73371.103Skamil SYSCALL_REQUIRE( 73381.103Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 73391.103Skamil 73401.103Skamil DPRINTF("Before resuming the child process where it left off " 73411.103Skamil "and without signal to be sent\n"); 73421.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 73431.103Skamil 73441.103Skamil if (flags & CLONE_VFORK) { 73451.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 73461.103Skamil child); 73471.103Skamil TWAIT_REQUIRE_SUCCESS( 73481.103Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 73491.103Skamil 73501.103Skamil validate_status_stopped(status, SIGTRAP); 73511.103Skamil 73521.103Skamil name[3] = child; 73531.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 73541.103Skamil 73551.103Skamil /* 73561.103Skamil * SIGCHLD is now pending in the signal queue and 73571.103Skamil * the kernel presents it to userland as a masked signal. 73581.103Skamil */ 73591.103Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 73601.103Skamil 73611.103Skamil if (masked) { 73621.103Skamil DPRINTF("kp_sigmask=" 73631.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73641.103Skamil PRIx32 "\n", 73651.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 73661.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 73671.103Skamil 73681.103Skamil DPRINTF("kp.p_sigmask=" 73691.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73701.103Skamil PRIx32 "\n", 73711.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 73721.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 73731.103Skamil 73741.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 73751.103Skamil sizeof(kp_sigmask))); 73761.103Skamil } 73771.103Skamil 73781.103Skamil if (ignored) { 73791.103Skamil DPRINTF("kp_sigignore=" 73801.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73811.103Skamil PRIx32 "\n", 73821.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 73831.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 73841.103Skamil 73851.103Skamil DPRINTF("kp.p_sigignore=" 73861.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73871.103Skamil PRIx32 "\n", 73881.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 73891.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 73901.103Skamil 73911.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 73921.103Skamil sizeof(kp_sigignore))); 73931.103Skamil } 73941.103Skamil 73951.103Skamil SYSCALL_REQUIRE( 73961.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 73971.103Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 73981.103Skamil 73991.103Skamil child2 = state.pe_other_pid; 74001.103Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 74011.103Skamil child2); 74021.103Skamil 74031.103Skamil DPRINTF("Before resuming the child process where it left off " 74041.103Skamil "and without signal to be sent\n"); 74051.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 74061.103Skamil } 74071.103Skamil 74081.103Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 74091.103Skamil "\n", TWAIT_FNAME); 74101.103Skamil TWAIT_REQUIRE_SUCCESS( 74111.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 74121.103Skamil 74131.103Skamil validate_status_exited(status, exitval2); 74141.103Skamil 74151.103Skamil DPRINTF("Before calling %s() for the forkee - expected no " 74161.103Skamil "process\n", TWAIT_FNAME); 74171.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 74181.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 74191.103Skamil 74201.103Skamil DPRINTF("Before calling %s() for the child - expected stopped " 74211.103Skamil "SIGCHLD\n", TWAIT_FNAME); 74221.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74231.103Skamil 74241.103Skamil validate_status_stopped(status, SIGCHLD); 74251.103Skamil 74261.103Skamil DPRINTF("Before resuming the child process where it left off and " 74271.103Skamil "without signal to be sent\n"); 74281.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 74291.103Skamil 74301.103Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 74311.103Skamil TWAIT_FNAME); 74321.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74331.103Skamil 74341.103Skamil validate_status_exited(status, exitval); 74351.103Skamil 74361.103Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 74371.103Skamil TWAIT_FNAME); 74381.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 74391.103Skamil} 74401.103Skamil 74411.106Skamil#define CLONE_TEST2(name,flags,masked,ignored) \ 74421.103SkamilATF_TC(name); \ 74431.103SkamilATF_TC_HEAD(name, tc) \ 74441.103Skamil{ \ 74451.103Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\ 74461.103Skamil " regardless of signal %s%s", \ 74471.103Skamil #flags, masked ? "masked" : "", ignored ? "ignored" : ""); \ 74481.103Skamil} \ 74491.103Skamil \ 74501.103SkamilATF_TC_BODY(name, tc) \ 74511.103Skamil{ \ 74521.103Skamil \ 74531.106Skamil clone_body2(flags, masked, ignored); \ 74541.103Skamil} 74551.103Skamil 74561.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false) 74571.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true) 74581.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false) 74591.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true) 74601.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false) 74611.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true) 74621.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false) 74631.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true) 74641.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX 74651.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true) // XXX 74661.110Skamil#if TEST_VFORK_ENABLED 74671.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false) 74681.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true) 74691.103Skamil#endif 74701.110Skamil#endif 74711.103Skamil 74721.103Skamil/// ---------------------------------------------------------------------------- 74731.103Skamil 74741.111Skamil#if TEST_VFORK_ENABLED 74751.107Skamil#if defined(TWAIT_HAVE_PID) 74761.107Skamilstatic void 74771.107Skamiltraceme_vfork_clone_body(int flags) 74781.107Skamil{ 74791.107Skamil const int exitval = 5; 74801.107Skamil const int exitval2 = 15; 74811.107Skamil pid_t child, child2 = 0, wpid; 74821.107Skamil#if defined(TWAIT_HAVE_STATUS) 74831.107Skamil int status; 74841.107Skamil#endif 74851.107Skamil 74861.107Skamil const size_t stack_size = 1024 * 1024; 74871.107Skamil void *stack, *stack_base; 74881.107Skamil 74891.107Skamil stack = malloc(stack_size); 74901.107Skamil ATF_REQUIRE(stack != NULL); 74911.107Skamil 74921.107Skamil#ifdef __MACHINE_STACK_GROWS_UP 74931.107Skamil stack_base = stack; 74941.107Skamil#else 74951.107Skamil stack_base = (char *)stack + stack_size; 74961.107Skamil#endif 74971.107Skamil 74981.107Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 74991.107Skamil if (child == 0) { 75001.107Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 75011.107Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 75021.107Skamil 75031.107Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 75041.107Skamil flags); 75051.107Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 75061.107Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 75071.107Skamil 75081.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 75091.107Skamil child2); 75101.107Skamil 75111.107Skamil // XXX WALLSIG? 75121.107Skamil FORKEE_REQUIRE_SUCCESS 75131.107Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 75141.107Skamil 75151.107Skamil forkee_status_exited(status, exitval2); 75161.107Skamil 75171.107Skamil DPRINTF("Before exiting of the child process\n"); 75181.107Skamil _exit(exitval); 75191.107Skamil } 75201.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 75211.107Skamil 75221.107Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 75231.107Skamil TWAIT_FNAME); 75241.107Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75251.107Skamil 75261.107Skamil validate_status_exited(status, exitval); 75271.107Skamil 75281.107Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 75291.107Skamil TWAIT_FNAME); 75301.107Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 75311.107Skamil} 75321.107Skamil 75331.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags) \ 75341.107SkamilATF_TC(name); \ 75351.107SkamilATF_TC_HEAD(name, tc) \ 75361.107Skamil{ \ 75371.107Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is " \ 75381.107Skamil "handled correctly with vfork(2)ed tracer", \ 75391.107Skamil #flags); \ 75401.107Skamil} \ 75411.107Skamil \ 75421.107SkamilATF_TC_BODY(name, tc) \ 75431.107Skamil{ \ 75441.107Skamil \ 75451.107Skamil traceme_vfork_clone_body(flags); \ 75461.107Skamil} 75471.107Skamil 75481.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0) 75491.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM) 75501.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS) 75511.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES) 75521.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND) // XXX 75531.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK) 75541.107Skamil#endif 75551.110Skamil#endif 75561.107Skamil 75571.107Skamil/// ---------------------------------------------------------------------------- 75581.107Skamil 75591.122Skamilstatic void 75601.122Skamiluser_va0_disable(int operation) 75611.122Skamil{ 75621.122Skamil pid_t child, wpid; 75631.122Skamil#if defined(TWAIT_HAVE_STATUS) 75641.122Skamil int status; 75651.122Skamil#endif 75661.122Skamil const int sigval = SIGSTOP; 75671.122Skamil int rv; 75681.122Skamil 75691.122Skamil struct ptrace_siginfo info; 75701.122Skamil 75711.122Skamil if (get_user_va0_disable() == 0) 75721.122Skamil atf_tc_skip("vm.user_va0_disable is set to 0"); 75731.122Skamil 75741.122Skamil memset(&info, 0, sizeof(info)); 75751.122Skamil 75761.122Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 75771.122Skamil SYSCALL_REQUIRE((child = fork()) != -1); 75781.122Skamil if (child == 0) { 75791.122Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 75801.122Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 75811.122Skamil 75821.122Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 75831.122Skamil FORKEE_ASSERT(raise(sigval) == 0); 75841.122Skamil 75851.122Skamil /* NOTREACHED */ 75861.122Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 75871.122Skamil __unreachable(); 75881.122Skamil } 75891.122Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 75901.122Skamil 75911.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75921.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75931.122Skamil 75941.122Skamil validate_status_stopped(status, sigval); 75951.122Skamil 75961.122Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 75971.122Skamil "child\n"); 75981.122Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 75991.122Skamil sizeof(info)) != -1); 76001.122Skamil 76011.122Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 76021.122Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 76031.122Skamil "si_errno=%#x\n", 76041.122Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 76051.122Skamil info.psi_siginfo.si_errno); 76061.122Skamil 76071.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 76081.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 76091.122Skamil 76101.122Skamil DPRINTF("Before resuming the child process in PC=0x0 " 76111.122Skamil "and without signal to be sent\n"); 76121.122Skamil errno = 0; 76131.122Skamil rv = ptrace(operation, child, (void *)0, 0); 76141.122Skamil ATF_REQUIRE_EQ(errno, EINVAL); 76151.122Skamil ATF_REQUIRE_EQ(rv, -1); 76161.122Skamil 76171.122Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 76181.122Skamil 76191.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76201.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 76211.122Skamil validate_status_signaled(status, SIGKILL, 0); 76221.122Skamil 76231.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76241.122Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 76251.122Skamil} 76261.122Skamil 76271.122Skamil#define USER_VA0_DISABLE(test, operation) \ 76281.122SkamilATF_TC(test); \ 76291.122SkamilATF_TC_HEAD(test, tc) \ 76301.122Skamil{ \ 76311.122Skamil atf_tc_set_md_var(tc, "descr", \ 76321.122Skamil "Verify behavior of " #operation " with PC set to 0x0"); \ 76331.122Skamil} \ 76341.122Skamil \ 76351.122SkamilATF_TC_BODY(test, tc) \ 76361.122Skamil{ \ 76371.122Skamil \ 76381.122Skamil user_va0_disable(operation); \ 76391.122Skamil} 76401.122Skamil 76411.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE) 76421.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL) 76431.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH) 76441.122Skamil 76451.122Skamil/// ---------------------------------------------------------------------------- 76461.122Skamil 76471.130Smgorny/* 76481.130Smgorny * Parse the core file and find the requested note. If the reading or parsing 76491.130Smgorny * fails, the test is failed. If the note is found, it is read onto buf, up to 76501.130Smgorny * buf_len. The actual length of the note is returned (which can be greater 76511.130Smgorny * than buf_len, indicating that it has been truncated). If the note is not 76521.130Smgorny * found, -1 is returned. 76531.130Smgorny */ 76541.130Smgornystatic ssize_t core_find_note(const char *core_path, 76551.130Smgorny const char *note_name, uint64_t note_type, void *buf, size_t buf_len) 76561.130Smgorny{ 76571.130Smgorny int core_fd; 76581.130Smgorny Elf *core_elf; 76591.130Smgorny size_t core_numhdr, i; 76601.130Smgorny ssize_t ret = -1; 76611.130Smgorny /* note: we assume note name will be null-terminated */ 76621.130Smgorny size_t name_len = strlen(note_name) + 1; 76631.130Smgorny 76641.130Smgorny SYSCALL_REQUIRE((core_fd = open(core_path, O_RDONLY)) != -1); 76651.130Smgorny SYSCALL_REQUIRE(elf_version(EV_CURRENT) != EV_NONE); 76661.130Smgorny SYSCALL_REQUIRE((core_elf = elf_begin(core_fd, ELF_C_READ, NULL))); 76671.130Smgorny 76681.130Smgorny SYSCALL_REQUIRE(elf_getphnum(core_elf, &core_numhdr) != 0); 76691.130Smgorny for (i = 0; i < core_numhdr && ret == -1; i++) { 76701.130Smgorny GElf_Phdr core_hdr; 76711.130Smgorny size_t offset; 76721.130Smgorny SYSCALL_REQUIRE(gelf_getphdr(core_elf, i, &core_hdr)); 76731.130Smgorny if (core_hdr.p_type != PT_NOTE) 76741.130Smgorny continue; 76751.130Smgorny 76761.130Smgorny for (offset = core_hdr.p_offset; 76771.130Smgorny offset < core_hdr.p_offset + core_hdr.p_filesz;) { 76781.130Smgorny Elf64_Nhdr note_hdr; 76791.130Smgorny char name_buf[64]; 76801.130Smgorny 76811.130Smgorny switch (gelf_getclass(core_elf)) { 76821.130Smgorny case ELFCLASS64: 76831.130Smgorny SYSCALL_REQUIRE(pread(core_fd, ¬e_hdr, 76841.130Smgorny sizeof(note_hdr), offset) 76851.130Smgorny == sizeof(note_hdr)); 76861.130Smgorny offset += sizeof(note_hdr); 76871.130Smgorny break; 76881.130Smgorny case ELFCLASS32: 76891.130Smgorny { 76901.130Smgorny Elf32_Nhdr tmp_hdr; 76911.130Smgorny SYSCALL_REQUIRE(pread(core_fd, &tmp_hdr, 76921.130Smgorny sizeof(tmp_hdr), offset) 76931.130Smgorny == sizeof(tmp_hdr)); 76941.130Smgorny offset += sizeof(tmp_hdr); 76951.130Smgorny note_hdr.n_namesz = tmp_hdr.n_namesz; 76961.130Smgorny note_hdr.n_descsz = tmp_hdr.n_descsz; 76971.130Smgorny note_hdr.n_type = tmp_hdr.n_type; 76981.130Smgorny } 76991.130Smgorny break; 77001.130Smgorny } 77011.130Smgorny 77021.130Smgorny /* indicates end of notes */ 77031.130Smgorny if (note_hdr.n_namesz == 0 || note_hdr.n_descsz == 0) 77041.130Smgorny break; 77051.130Smgorny if (note_hdr.n_namesz == name_len && 77061.130Smgorny note_hdr.n_namesz <= sizeof(name_buf)) { 77071.130Smgorny SYSCALL_REQUIRE(pread(core_fd, name_buf, 77081.130Smgorny note_hdr.n_namesz, offset) 77091.130Smgorny == note_hdr.n_namesz); 77101.130Smgorny 77111.130Smgorny if (!strncmp(note_name, name_buf, name_len) && 77121.130Smgorny note_hdr.n_type == note_type) 77131.130Smgorny ret = note_hdr.n_descsz; 77141.130Smgorny } 77151.130Smgorny 77161.130Smgorny offset += note_hdr.n_namesz; 77171.130Smgorny /* fix to alignment */ 77181.130Smgorny offset = ((offset + core_hdr.p_align - 1) 77191.130Smgorny / core_hdr.p_align) * core_hdr.p_align; 77201.130Smgorny 77211.130Smgorny /* if name & type matched above */ 77221.130Smgorny if (ret != -1) { 77231.130Smgorny ssize_t read_len = MIN(buf_len, 77241.130Smgorny note_hdr.n_descsz); 77251.130Smgorny SYSCALL_REQUIRE(pread(core_fd, buf, 77261.130Smgorny read_len, offset) == read_len); 77271.130Smgorny break; 77281.130Smgorny } 77291.130Smgorny 77301.130Smgorny offset += note_hdr.n_descsz; 77311.130Smgorny } 77321.130Smgorny } 77331.130Smgorny 77341.130Smgorny elf_end(core_elf); 77351.130Smgorny close(core_fd); 77361.130Smgorny 77371.130Smgorny return ret; 77381.130Smgorny} 77391.130Smgorny 77401.130SmgornyATF_TC(core_dump_procinfo); 77411.130SmgornyATF_TC_HEAD(core_dump_procinfo, tc) 77421.130Smgorny{ 77431.130Smgorny atf_tc_set_md_var(tc, "descr", 77441.130Smgorny "Trigger a core dump and verify its contents."); 77451.130Smgorny} 77461.130Smgorny 77471.130SmgornyATF_TC_BODY(core_dump_procinfo, tc) 77481.130Smgorny{ 77491.130Smgorny const int exitval = 5; 77501.130Smgorny pid_t child, wpid; 77511.130Smgorny#if defined(TWAIT_HAVE_STATUS) 77521.130Smgorny const int sigval = SIGTRAP; 77531.130Smgorny int status; 77541.130Smgorny#endif 77551.130Smgorny char core_path[] = "/tmp/core.XXXXXX"; 77561.130Smgorny int core_fd; 77571.130Smgorny struct netbsd_elfcore_procinfo procinfo; 77581.130Smgorny 77591.130Smgorny DPRINTF("Before forking process PID=%d\n", getpid()); 77601.130Smgorny SYSCALL_REQUIRE((child = fork()) != -1); 77611.130Smgorny if (child == 0) { 77621.130Smgorny DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 77631.130Smgorny FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 77641.130Smgorny 77651.130Smgorny DPRINTF("Before triggering SIGTRAP\n"); 77661.130Smgorny trigger_trap(); 77671.130Smgorny 77681.130Smgorny DPRINTF("Before exiting of the child process\n"); 77691.130Smgorny _exit(exitval); 77701.130Smgorny } 77711.130Smgorny DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 77721.130Smgorny 77731.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 77741.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 77751.130Smgorny 77761.130Smgorny validate_status_stopped(status, sigval); 77771.130Smgorny 77781.130Smgorny SYSCALL_REQUIRE((core_fd = mkstemp(core_path)) != -1); 77791.130Smgorny close(core_fd); 77801.130Smgorny 77811.130Smgorny DPRINTF("Call DUMPCORE for the child process\n"); 77821.130Smgorny SYSCALL_REQUIRE(ptrace(PT_DUMPCORE, child, core_path, strlen(core_path)) 77831.130Smgorny != -1); 77841.130Smgorny 77851.130Smgorny DPRINTF("Read core file\n"); 77861.130Smgorny ATF_REQUIRE_EQ(core_find_note(core_path, "NetBSD-CORE", 77871.130Smgorny ELF_NOTE_NETBSD_CORE_PROCINFO, &procinfo, sizeof(procinfo)), 77881.130Smgorny sizeof(procinfo)); 77891.130Smgorny 77901.130Smgorny ATF_CHECK_EQ(procinfo.cpi_version, 1); 77911.130Smgorny ATF_CHECK_EQ(procinfo.cpi_cpisize, sizeof(procinfo)); 77921.130Smgorny ATF_CHECK_EQ(procinfo.cpi_signo, SIGTRAP); 77931.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pid, child); 77941.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ppid, getpid()); 77951.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pgrp, getpgid(child)); 77961.130Smgorny ATF_CHECK_EQ(procinfo.cpi_sid, getsid(child)); 77971.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ruid, getuid()); 77981.130Smgorny ATF_CHECK_EQ(procinfo.cpi_euid, geteuid()); 77991.130Smgorny ATF_CHECK_EQ(procinfo.cpi_rgid, getgid()); 78001.130Smgorny ATF_CHECK_EQ(procinfo.cpi_egid, getegid()); 78011.130Smgorny ATF_CHECK_EQ(procinfo.cpi_nlwps, 1); 78021.130Smgorny ATF_CHECK_EQ(procinfo.cpi_siglwp, 1); 78031.130Smgorny 78041.130Smgorny unlink(core_path); 78051.130Smgorny 78061.130Smgorny DPRINTF("Before resuming the child process where it left off and " 78071.130Smgorny "without signal to be sent\n"); 78081.130Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 78091.130Smgorny 78101.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 78111.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 78121.130Smgorny 78131.130Smgorny validate_status_exited(status, exitval); 78141.130Smgorny 78151.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 78161.130Smgorny TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 78171.130Smgorny} 78181.130Smgorny 78191.130Smgorny/// ---------------------------------------------------------------------------- 78201.130Smgorny 78211.1Skamil#include "t_ptrace_amd64_wait.h" 78221.1Skamil#include "t_ptrace_i386_wait.h" 78231.1Skamil#include "t_ptrace_x86_wait.h" 78241.1Skamil 78251.1SkamilATF_TP_ADD_TCS(tp) 78261.1Skamil{ 78271.1Skamil setvbuf(stdout, NULL, _IONBF, 0); 78281.1Skamil setvbuf(stderr, NULL, _IONBF, 0); 78291.33Skamil 78301.36Skamil ATF_TP_ADD_TC(tp, traceme_raise1); 78311.33Skamil ATF_TP_ADD_TC(tp, traceme_raise2); 78321.33Skamil ATF_TP_ADD_TC(tp, traceme_raise3); 78331.33Skamil ATF_TP_ADD_TC(tp, traceme_raise4); 78341.33Skamil ATF_TP_ADD_TC(tp, traceme_raise5); 78351.85Skamil ATF_TP_ADD_TC(tp, traceme_raise6); 78361.85Skamil ATF_TP_ADD_TC(tp, traceme_raise7); 78371.85Skamil ATF_TP_ADD_TC(tp, traceme_raise8); 78381.85Skamil ATF_TP_ADD_TC(tp, traceme_raise9); 78391.85Skamil ATF_TP_ADD_TC(tp, traceme_raise10); 78401.33Skamil 78411.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1); 78421.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2); 78431.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3); 78441.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4); 78451.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5); 78461.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6); 78471.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7); 78481.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8); 78491.87Skamil 78501.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1); 78511.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2); 78521.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3); 78531.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4); 78541.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5); 78551.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6); 78561.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7); 78571.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8); 78581.86Skamil 78591.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_trap); 78601.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_segv); 78611.71Skamil ATF_TP_ADD_TC(tp, traceme_crash_ill); 78621.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_fpe); 78631.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_bus); 78641.59Skamil 78651.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap); 78661.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv); 78671.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill); 78681.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe); 78691.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus); 78701.88Skamil 78711.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap); 78721.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv); 78731.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill); 78741.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe); 78751.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus); 78761.88Skamil 78771.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1); 78781.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2); 78791.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3); 78801.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4); 78811.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5); 78821.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6); 78831.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7); 78841.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8); 78851.50Skamil 78861.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1); 78871.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2); 78881.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3); 78891.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4); 78901.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5); 78911.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6); 78921.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7); 78931.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8); 78941.50Skamil 78951.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1); 78961.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2); 78971.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3); 78981.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4); 78991.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5); 79001.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6); 79011.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7); 79021.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8); 79031.50Skamil 79041.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1); 79051.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2); 79061.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3); 79071.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4); 79081.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5); 79091.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6); 79101.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7); 79111.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8); 79121.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9); 79131.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10); 79141.1Skamil 79151.37Skamil ATF_TP_ADD_TC(tp, traceme_pid1_parent); 79161.37Skamil 79171.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise1); 79181.46Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise2); 79191.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise3); 79201.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise4); 79211.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise5); 79221.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise6); 79231.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise7); 79241.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise8); 79251.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise9); 79261.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise10); 79271.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise11); 79281.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise12); 79291.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise13); 79301.40Skamil 79311.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap); 79321.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv); 79331.71Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill); 79341.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe); 79351.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus); 79361.41Skamil 79371.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap); 79381.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv); 79391.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill); 79401.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe); 79411.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus); 79421.92Skamil 79431.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap); 79441.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv); 79451.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill); 79461.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe); 79471.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus); 79481.92Skamil 79491.43Skamil ATF_TP_ADD_TC(tp, traceme_vfork_exec); 79501.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec); 79511.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec); 79521.43Skamil 79531.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap); 79541.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv); 79551.71Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill); 79561.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe); 79571.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus); 79581.59Skamil 79591.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79601.94Skamil unrelated_tracer_sees_signalmasked_crash_trap); 79611.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79621.94Skamil unrelated_tracer_sees_signalmasked_crash_segv); 79631.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79641.94Skamil unrelated_tracer_sees_signalmasked_crash_ill); 79651.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79661.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe); 79671.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79681.94Skamil unrelated_tracer_sees_signalmasked_crash_bus); 79691.94Skamil 79701.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79711.94Skamil unrelated_tracer_sees_signalignored_crash_trap); 79721.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79731.94Skamil unrelated_tracer_sees_signalignored_crash_segv); 79741.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79751.94Skamil unrelated_tracer_sees_signalignored_crash_ill); 79761.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79771.94Skamil unrelated_tracer_sees_signalignored_crash_fpe); 79781.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79791.94Skamil unrelated_tracer_sees_signalignored_crash_bus); 79801.94Skamil 79811.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent); 79821.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates); 79831.61Skre ATF_TP_ADD_TC_HAVE_PID(tp, 79841.61Skre unrelated_tracer_sees_terminaton_before_the_parent); 79851.67Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process); 79861.51Skamil 79871.51Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_child); 79881.66Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child); 79891.51Skamil 79901.51Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_parent); 79911.65Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent); 79921.51Skamil 79931.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79941.51Skamil tracee_sees_its_original_parent_getppid); 79951.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79961.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2); 79971.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79981.51Skamil tracee_sees_its_original_parent_procfs_status); 79991.1Skamil 80001.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_empty); 80011.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_fork); 80021.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork); 80031.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done); 80041.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create); 80051.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit); 80061.125Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_posix_spawn); 80071.1Skamil 80081.31Skamil ATF_TP_ADD_TC(tp, fork1); 80091.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork2); 80101.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork3); 80111.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork4); 80121.31Skamil ATF_TP_ADD_TC(tp, fork5); 80131.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork6); 80141.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork7); 80151.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork8); 80161.125Skamil ATF_TP_ADD_TC(tp, fork9); 80171.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork10); 80181.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork11); 80191.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork12); 80201.125Skamil ATF_TP_ADD_TC(tp, fork13); 80211.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork14); 80221.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork15); 80231.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork16); 80241.31Skamil 80251.109Skamil#if TEST_VFORK_ENABLED 80261.31Skamil ATF_TP_ADD_TC(tp, vfork1); 80271.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork2); 80281.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork3); 80291.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork4); 80301.31Skamil ATF_TP_ADD_TC(tp, vfork5); 80311.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork6); 80321.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork7); 80331.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork8); 80341.125Skamil ATF_TP_ADD_TC(tp, vfork9); 80351.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork10); 80361.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork11); 80371.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork12); 80381.125Skamil ATF_TP_ADD_TC(tp, vfork13); 80391.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork14); 80401.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork15); 80411.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork16); 80421.116Skamil#endif 80431.1Skamil 80441.124Skamil ATF_TP_ADD_TC(tp, posix_spawn1); 80451.125Skamil ATF_TP_ADD_TC(tp, posix_spawn2); 80461.125Skamil ATF_TP_ADD_TC(tp, posix_spawn3); 80471.125Skamil ATF_TP_ADD_TC(tp, posix_spawn4); 80481.124Skamil ATF_TP_ADD_TC(tp, posix_spawn5); 80491.125Skamil ATF_TP_ADD_TC(tp, posix_spawn6); 80501.125Skamil ATF_TP_ADD_TC(tp, posix_spawn7); 80511.125Skamil ATF_TP_ADD_TC(tp, posix_spawn8); 80521.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn9); 80531.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn10); 80541.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn11); 80551.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn12); 80561.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn13); 80571.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn14); 80581.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn15); 80591.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn16); 80601.124Skamil 80611.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_detach_spawner); 80621.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_detach_forker); 80631.116Skamil#if TEST_VFORK_ENABLED 80641.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforker); 80651.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforkerdone); 80661.116Skamil#endif 80671.126Skamil 80681.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_kill_spawner); 80691.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_kill_forker); 80701.116Skamil#if TEST_VFORK_ENABLED 80711.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforker); 80721.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforkerdone); 80731.116Skamil#endif 80741.116Skamil 80751.116Skamil#if TEST_VFORK_ENABLED 80761.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_fork); 80771.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_vfork); 80781.109Skamil#endif 80791.108Skamil 80801.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8); 80811.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16); 80821.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32); 80831.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64); 80841.54Skamil 80851.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8); 80861.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16); 80871.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32); 80881.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64); 80891.54Skamil 80901.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8); 80911.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16); 80921.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32); 80931.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64); 80941.54Skamil 80951.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8); 80961.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16); 80971.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32); 80981.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64); 80991.54Skamil 81001.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d); 81011.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i); 81021.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d); 81031.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i); 81041.54Skamil 81051.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text); 81061.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text); 81071.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text); 81081.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text); 81091.54Skamil 81101.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text); 81111.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text); 81121.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text); 81131.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text); 81141.54Skamil 81151.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text); 81161.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text); 81171.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text); 81181.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text); 81191.54Skamil 81201.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text); 81211.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text); 81221.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text); 81231.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text); 81241.54Skamil 81251.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text); 81261.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text); 81271.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text); 81281.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text); 81291.1Skamil 81301.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv); 81311.1Skamil 81321.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i); 81331.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d); 81341.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i); 81351.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d); 81361.101Skamil 81371.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i); 81381.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d); 81391.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i); 81401.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d); 81411.101Skamil 81421.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv); 81431.101Skamil 81441.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i); 81451.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d); 81461.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i); 81471.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d); 81481.115Skamil 81491.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i); 81501.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d); 81511.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i); 81521.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d); 81531.115Skamil 81541.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1); 81551.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2); 81561.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3); 81571.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4); 81581.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5); 81591.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6); 81601.1Skamil 81611.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1); 81621.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2); 81631.1Skamil 81641.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step1); 81651.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step2); 81661.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step3); 81671.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step4); 81681.1Skamil 81691.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep1); 81701.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep2); 81711.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep3); 81721.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep4); 81731.2Skamil 81741.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked); 81751.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored); 81761.95Skamil 81771.1Skamil ATF_TP_ADD_TC(tp, kill1); 81781.1Skamil ATF_TP_ADD_TC(tp, kill2); 81791.75Skamil ATF_TP_ADD_TC(tp, kill3); 81801.1Skamil 81811.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0); 81821.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1); 81831.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2); 81841.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3); 81851.77Skamil 81861.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0); 81871.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1); 81881.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2); 81891.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3); 81901.1Skamil 81911.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_unmodified); 81921.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_faked); 81931.79Skamil 81941.82Skamil ATF_TP_ADD_TC(tp, traceme_exec); 81951.97Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_exec); 81961.97Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_exec); 81971.1Skamil 81981.119Skamil ATF_TP_ADD_TC(tp, trace_thread_nolwpevents); 81991.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpexit); 82001.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate); 82011.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit); 82021.1Skamil 82031.84Skamil ATF_TP_ADD_TC(tp, signal_mask_unrelated); 82041.84Skamil 82051.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalmasked); 82061.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalignored); 82071.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked); 82081.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored); 82091.109Skamil#if TEST_VFORK_ENABLED 82101.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked); 82111.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored); 82121.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked); 82131.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored); 82141.109Skamil#endif 82151.99Skamil 82161.1Skamil ATF_TP_ADD_TC(tp, signal9); 82171.1Skamil ATF_TP_ADD_TC(tp, signal10); 82181.1Skamil 82191.1Skamil ATF_TP_ADD_TC(tp, suspend1); 82201.1Skamil ATF_TP_ADD_TC(tp, suspend2); 82211.1Skamil 82221.1Skamil ATF_TP_ADD_TC(tp, resume1); 82231.1Skamil 82241.1Skamil ATF_TP_ADD_TC(tp, syscall1); 82251.1Skamil 82261.1Skamil ATF_TP_ADD_TC(tp, syscallemu1); 82271.1Skamil 82281.106Skamil ATF_TP_ADD_TC(tp, clone1); 82291.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone2); 82301.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone3); 82311.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone4); 82321.106Skamil ATF_TP_ADD_TC(tp, clone5); 82331.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone6); 82341.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone7); 82351.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone8); 82361.106Skamil 82371.106Skamil ATF_TP_ADD_TC(tp, clone_vm1); 82381.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2); 82391.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3); 82401.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4); 82411.106Skamil ATF_TP_ADD_TC(tp, clone_vm5); 82421.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6); 82431.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7); 82441.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8); 82451.106Skamil 82461.106Skamil ATF_TP_ADD_TC(tp, clone_fs1); 82471.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2); 82481.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3); 82491.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4); 82501.106Skamil ATF_TP_ADD_TC(tp, clone_fs5); 82511.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6); 82521.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7); 82531.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8); 82541.106Skamil 82551.106Skamil ATF_TP_ADD_TC(tp, clone_files1); 82561.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2); 82571.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3); 82581.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4); 82591.106Skamil ATF_TP_ADD_TC(tp, clone_files5); 82601.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6); 82611.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7); 82621.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8); 82631.106Skamil 82641.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand1); // XXX 82651.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX 82661.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX 82671.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX 82681.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand5); // XXX 82691.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX 82701.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX 82711.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX 82721.106Skamil 82731.109Skamil#if TEST_VFORK_ENABLED 82741.106Skamil ATF_TP_ADD_TC(tp, clone_vfork1); 82751.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2); 82761.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3); 82771.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4); 82781.106Skamil ATF_TP_ADD_TC(tp, clone_vfork5); 82791.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6); 82801.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7); 82811.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8); 82821.109Skamil#endif 82831.106Skamil 82841.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored); 82851.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked); 82861.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored); 82871.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked); 82881.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored); 82891.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked); 82901.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored); 82911.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked); 82921.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX 82931.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX 82941.109Skamil#if TEST_VFORK_ENABLED 82951.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored); 82961.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked); 82971.109Skamil#endif 82981.103Skamil 82991.109Skamil#if TEST_VFORK_ENABLED 83001.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone); 83011.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm); 83021.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs); 83031.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files); 83041.107Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX 83051.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork); 83061.109Skamil#endif 83071.107Skamil 83081.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue); 83091.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall); 83101.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach); 83111.122Skamil 83121.130Smgorny ATF_TP_ADD_TC(tp, core_dump_procinfo); 83131.130Smgorny 83141.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64(); 83151.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_I386(); 83161.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_X86(); 83171.1Skamil 83181.1Skamil return atf_no_error(); 83191.1Skamil} 8320