t_ptrace_wait.c revision 1.132
11.132Skamil/* $NetBSD: t_ptrace_wait.c,v 1.132 2019/10/01 21:13:30 kamil Exp $ */ 21.1Skamil 31.1Skamil/*- 41.78Skamil * Copyright (c) 2016, 2017, 2018, 2019 The NetBSD Foundation, Inc. 51.1Skamil * All rights reserved. 61.1Skamil * 71.1Skamil * Redistribution and use in source and binary forms, with or without 81.1Skamil * modification, are permitted provided that the following conditions 91.1Skamil * are met: 101.1Skamil * 1. Redistributions of source code must retain the above copyright 111.1Skamil * notice, this list of conditions and the following disclaimer. 121.1Skamil * 2. Redistributions in binary form must reproduce the above copyright 131.1Skamil * notice, this list of conditions and the following disclaimer in the 141.1Skamil * documentation and/or other materials provided with the distribution. 151.1Skamil * 161.1Skamil * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 171.1Skamil * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 181.1Skamil * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 191.1Skamil * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 201.1Skamil * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 211.1Skamil * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 221.1Skamil * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 231.1Skamil * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 241.1Skamil * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 251.1Skamil * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 261.1Skamil * POSSIBILITY OF SUCH DAMAGE. 271.1Skamil */ 281.1Skamil 291.1Skamil#include <sys/cdefs.h> 301.132Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.132 2019/10/01 21:13:30 kamil Exp $"); 311.1Skamil 321.1Skamil#include <sys/param.h> 331.1Skamil#include <sys/types.h> 341.130Smgorny#include <sys/exec_elf.h> 351.39Skamil#include <sys/mman.h> 361.1Skamil#include <sys/ptrace.h> 371.1Skamil#include <sys/resource.h> 381.1Skamil#include <sys/stat.h> 391.1Skamil#include <sys/syscall.h> 401.1Skamil#include <sys/sysctl.h> 411.129Smgorny#include <sys/uio.h> 421.1Skamil#include <sys/wait.h> 431.1Skamil#include <machine/reg.h> 441.132Skamil#include <assert.h> 451.1Skamil#include <elf.h> 461.1Skamil#include <err.h> 471.1Skamil#include <errno.h> 481.130Smgorny#include <fcntl.h> 491.1Skamil#include <lwp.h> 501.77Skamil#include <pthread.h> 511.1Skamil#include <sched.h> 521.1Skamil#include <signal.h> 531.124Skamil#include <spawn.h> 541.1Skamil#include <stdint.h> 551.1Skamil#include <stdio.h> 561.1Skamil#include <stdlib.h> 571.1Skamil#include <strings.h> 581.26Skamil#include <time.h> 591.1Skamil#include <unistd.h> 601.1Skamil 611.114Skamil#include <fenv.h> 621.114Skamil#if (__arm__ && !__SOFTFP__) || __aarch64__ 631.114Skamil#include <ieeefp.h> /* only need for ARM Cortex/Neon hack */ 641.114Skamil#endif 651.114Skamil 661.121Smgorny#if defined(__i386__) || defined(__x86_64__) 671.121Smgorny#include <cpuid.h> 681.121Smgorny#include <x86/cpu_extended_state.h> 691.129Smgorny#include <x86/specialreg.h> 701.121Smgorny#endif 711.121Smgorny 721.130Smgorny#include <libelf.h> 731.130Smgorny#include <gelf.h> 741.130Smgorny 751.1Skamil#include <atf-c.h> 761.1Skamil 771.132Skamil/* Assumptions in the kernel code that must be kept. */ 781.132Skamilstatic_assert(sizeof(((struct ptrace_state *)0)->pe_report_event) == 791.132Skamil sizeof(((siginfo_t *)0)->si_pe_report_event), 801.132Skamil "pe_report_event and si_pe_report_event must be of the same size"); 811.132Skamilstatic_assert(sizeof(((struct ptrace_state *)0)->pe_other_pid) == 821.132Skamil sizeof(((siginfo_t *)0)->si_pe_other_pid), 831.132Skamil "pe_other_pid and si_pe_other_pid must be of the same size"); 841.132Skamilstatic_assert(sizeof(((struct ptrace_state *)0)->pe_lwp) == 851.132Skamil sizeof(((siginfo_t *)0)->si_pe_lwp), 861.132Skamil "pe_lwp and si_pe_lwp must be of the same size"); 871.132Skamilstatic_assert(sizeof(((struct ptrace_state *)0)->pe_other_pid) == 881.132Skamil sizeof(((struct ptrace_state *)0)->pe_lwp), 891.132Skamil "pe_other_pid and pe_lwp must be of the same size"); 901.132Skamil 911.1Skamil#include "h_macros.h" 921.1Skamil 931.1Skamil#include "t_ptrace_wait.h" 941.1Skamil#include "msg.h" 951.1Skamil 961.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \ 971.61Skre SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \ 981.61Skre sizeof(msg)) == 0) 991.1Skamil 1001.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \ 1011.61Skre FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \ 1021.61Skre sizeof(msg)) == 0) 1031.1Skamil 1041.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \ 1051.61Skre FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \ 1061.61Skre sizeof(msg)) == 0) 1071.1Skamil 1081.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \ 1091.61Skre SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \ 1101.61Skre sizeof(msg)) == 0) 1111.13Schristos 1121.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \ 1131.13Schristos strerror(errno)) 1141.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \ 1151.18Schristos "%d(%s) != %d", res, strerror(res), exp) 1161.13Schristos 1171.13Schristosstatic int debug = 0; 1181.13Schristos 1191.13Schristos#define DPRINTF(a, ...) do \ 1201.123Skamil if (debug) \ 1211.123Skamil printf("%s() %s:%d " a, __func__, __FILE__, __LINE__, ##__VA_ARGS__); \ 1221.13Schristos while (/*CONSTCOND*/0) 1231.1Skamil 1241.110Skamil#ifndef TEST_VFORK_ENABLED 1251.127Skamil#define TEST_VFORK_ENABLED 1 1261.110Skamil#endif 1271.109Skamil 1281.128Skamil#ifndef TEST_LWP_ENABLED 1291.128Skamil#define TEST_LWP_ENABLED 0 1301.128Skamil#endif 1311.128Skamil 1321.34Skamil/// ---------------------------------------------------------------------------- 1331.34Skamil 1341.33Skamilstatic void 1351.33Skamiltraceme_raise(int sigval) 1361.1Skamil{ 1371.1Skamil const int exitval = 5; 1381.1Skamil pid_t child, wpid; 1391.1Skamil#if defined(TWAIT_HAVE_STATUS) 1401.1Skamil int status; 1411.1Skamil#endif 1421.1Skamil 1431.45Skamil struct ptrace_siginfo info; 1441.45Skamil memset(&info, 0, sizeof(info)); 1451.45Skamil 1461.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 1471.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 1481.1Skamil if (child == 0) { 1491.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1501.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1511.1Skamil 1521.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1531.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 1541.1Skamil 1551.36Skamil switch (sigval) { 1561.36Skamil case SIGKILL: 1571.36Skamil /* NOTREACHED */ 1581.36Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 1591.70Smrg __unreachable(); 1601.36Skamil default: 1611.36Skamil DPRINTF("Before exiting of the child process\n"); 1621.36Skamil _exit(exitval); 1631.36Skamil } 1641.1Skamil } 1651.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1661.1Skamil 1671.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1681.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1691.1Skamil 1701.36Skamil switch (sigval) { 1711.36Skamil case SIGKILL: 1721.36Skamil validate_status_signaled(status, sigval, 0); 1731.36Skamil break; 1741.36Skamil default: 1751.36Skamil validate_status_stopped(status, sigval); 1761.1Skamil 1771.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 1781.61Skre "child\n"); 1791.45Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 1801.61Skre sizeof(info)) != -1); 1811.45Skamil 1821.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1831.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 1841.61Skre "si_errno=%#x\n", 1851.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1861.61Skre info.psi_siginfo.si_errno); 1871.45Skamil 1881.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 1891.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 1901.45Skamil 1911.36Skamil DPRINTF("Before resuming the child process where it left off " 1921.36Skamil "and without signal to be sent\n"); 1931.36Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1941.1Skamil 1951.36Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1961.36Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 1971.61Skre child); 1981.36Skamil break; 1991.36Skamil } 2001.1Skamil 2011.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2021.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 2031.1Skamil} 2041.1Skamil 2051.61Skre#define TRACEME_RAISE(test, sig) \ 2061.61SkreATF_TC(test); \ 2071.61SkreATF_TC_HEAD(test, tc) \ 2081.61Skre{ \ 2091.61Skre atf_tc_set_md_var(tc, "descr", \ 2101.61Skre "Verify " #sig " followed by _exit(2) in a child"); \ 2111.61Skre} \ 2121.61Skre \ 2131.61SkreATF_TC_BODY(test, tc) \ 2141.61Skre{ \ 2151.61Skre \ 2161.61Skre traceme_raise(sig); \ 2171.33Skamil} 2181.33Skamil 2191.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */ 2201.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */ 2211.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */ 2221.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP) /* hangup */ 2231.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */ 2241.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */ 2251.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */ 2261.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */ 2271.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */ 2281.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */ 2291.33Skamil 2301.34Skamil/// ---------------------------------------------------------------------------- 2311.1Skamil 2321.1Skamilstatic void 2331.87Skamiltraceme_raisesignal_ignored(int sigignored) 2341.87Skamil{ 2351.87Skamil const int exitval = 5; 2361.87Skamil const int sigval = SIGSTOP; 2371.87Skamil pid_t child, wpid; 2381.87Skamil struct sigaction sa; 2391.87Skamil#if defined(TWAIT_HAVE_STATUS) 2401.87Skamil int status; 2411.87Skamil#endif 2421.87Skamil struct ptrace_siginfo info; 2431.87Skamil 2441.87Skamil memset(&info, 0, sizeof(info)); 2451.87Skamil 2461.87Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 2471.87Skamil SYSCALL_REQUIRE((child = fork()) != -1); 2481.87Skamil if (child == 0) { 2491.87Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2501.87Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2511.87Skamil 2521.87Skamil memset(&sa, 0, sizeof(sa)); 2531.87Skamil sa.sa_handler = SIG_IGN; 2541.87Skamil sigemptyset(&sa.sa_mask); 2551.87Skamil FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1); 2561.87Skamil 2571.87Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 2581.87Skamil FORKEE_ASSERT(raise(sigval) == 0); 2591.87Skamil 2601.87Skamil DPRINTF("Before raising %s from child\n", 2611.87Skamil strsignal(sigignored)); 2621.87Skamil FORKEE_ASSERT(raise(sigignored) == 0); 2631.87Skamil 2641.87Skamil DPRINTF("Before exiting of the child process\n"); 2651.87Skamil _exit(exitval); 2661.87Skamil } 2671.87Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2681.87Skamil 2691.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2701.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2711.87Skamil 2721.87Skamil validate_status_stopped(status, sigval); 2731.87Skamil 2741.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2751.87Skamil SYSCALL_REQUIRE( 2761.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2771.87Skamil 2781.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2791.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2801.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2811.87Skamil info.psi_siginfo.si_errno); 2821.87Skamil 2831.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 2841.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2851.87Skamil 2861.87Skamil DPRINTF("Before resuming the child process where it left off and " 2871.87Skamil "without signal to be sent\n"); 2881.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2891.87Skamil 2901.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2911.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2921.87Skamil 2931.87Skamil validate_status_stopped(status, sigignored); 2941.87Skamil 2951.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2961.87Skamil SYSCALL_REQUIRE( 2971.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2981.87Skamil 2991.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 3001.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 3011.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 3021.87Skamil info.psi_siginfo.si_errno); 3031.87Skamil 3041.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored); 3051.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 3061.87Skamil 3071.87Skamil DPRINTF("Before resuming the child process where it left off and " 3081.87Skamil "without signal to be sent\n"); 3091.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 3101.87Skamil 3111.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3121.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3131.87Skamil 3141.87Skamil validate_status_exited(status, exitval); 3151.87Skamil 3161.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3171.87Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 3181.87Skamil} 3191.87Skamil 3201.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig) \ 3211.87SkamilATF_TC(test); \ 3221.87SkamilATF_TC_HEAD(test, tc) \ 3231.87Skamil{ \ 3241.87Skamil atf_tc_set_md_var(tc, "descr", \ 3251.87Skamil "Verify that ignoring (with SIG_IGN) " #sig " in tracee " \ 3261.87Skamil "does not stop tracer from catching this raised signal"); \ 3271.87Skamil} \ 3281.87Skamil \ 3291.87SkamilATF_TC_BODY(test, tc) \ 3301.87Skamil{ \ 3311.87Skamil \ 3321.87Skamil traceme_raisesignal_ignored(sig); \ 3331.87Skamil} 3341.87Skamil 3351.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 3361.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */ 3371.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP) /* hangup */ 3381.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */ 3391.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */ 3401.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */ 3411.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */ 3421.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */ 3431.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */ 3441.87Skamil 3451.87Skamil/// ---------------------------------------------------------------------------- 3461.87Skamil 3471.87Skamilstatic void 3481.86Skamiltraceme_raisesignal_masked(int sigmasked) 3491.86Skamil{ 3501.86Skamil const int exitval = 5; 3511.86Skamil const int sigval = SIGSTOP; 3521.86Skamil pid_t child, wpid; 3531.86Skamil#if defined(TWAIT_HAVE_STATUS) 3541.86Skamil int status; 3551.86Skamil#endif 3561.86Skamil sigset_t intmask; 3571.86Skamil struct ptrace_siginfo info; 3581.86Skamil 3591.86Skamil memset(&info, 0, sizeof(info)); 3601.86Skamil 3611.86Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 3621.86Skamil SYSCALL_REQUIRE((child = fork()) != -1); 3631.86Skamil if (child == 0) { 3641.86Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 3651.86Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 3661.86Skamil 3671.86Skamil sigemptyset(&intmask); 3681.86Skamil sigaddset(&intmask, sigmasked); 3691.86Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 3701.86Skamil 3711.86Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 3721.86Skamil FORKEE_ASSERT(raise(sigval) == 0); 3731.86Skamil 3741.86Skamil DPRINTF("Before raising %s breakpoint from child\n", 3751.86Skamil strsignal(sigmasked)); 3761.86Skamil FORKEE_ASSERT(raise(sigmasked) == 0); 3771.86Skamil 3781.86Skamil DPRINTF("Before exiting of the child process\n"); 3791.86Skamil _exit(exitval); 3801.86Skamil } 3811.86Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 3821.86Skamil 3831.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3841.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3851.86Skamil 3861.86Skamil validate_status_stopped(status, sigval); 3871.86Skamil 3881.86Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 3891.86Skamil SYSCALL_REQUIRE( 3901.86Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 3911.86Skamil 3921.86Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 3931.86Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 3941.86Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 3951.86Skamil info.psi_siginfo.si_errno); 3961.86Skamil 3971.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 3981.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 3991.86Skamil 4001.86Skamil DPRINTF("Before resuming the child process where it left off and " 4011.86Skamil "without signal to be sent\n"); 4021.86Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 4031.86Skamil 4041.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4051.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4061.86Skamil 4071.86Skamil validate_status_exited(status, exitval); 4081.86Skamil 4091.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4101.86Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 4111.86Skamil} 4121.86Skamil 4131.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig) \ 4141.86SkamilATF_TC(test); \ 4151.86SkamilATF_TC_HEAD(test, tc) \ 4161.86Skamil{ \ 4171.86Skamil atf_tc_set_md_var(tc, "descr", \ 4181.86Skamil "Verify that masking (with SIG_BLOCK) " #sig " in tracee " \ 4191.86Skamil "stops tracer from catching this raised signal"); \ 4201.86Skamil} \ 4211.86Skamil \ 4221.86SkamilATF_TC_BODY(test, tc) \ 4231.86Skamil{ \ 4241.86Skamil \ 4251.86Skamil traceme_raisesignal_masked(sig); \ 4261.86Skamil} 4271.86Skamil 4281.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 4291.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */ 4301.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP) /* hangup */ 4311.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */ 4321.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */ 4331.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */ 4341.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */ 4351.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */ 4361.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */ 4371.86Skamil 4381.86Skamil/// ---------------------------------------------------------------------------- 4391.86Skamil 4401.86Skamilstatic void 4411.59Skamiltraceme_crash(int sig) 4421.59Skamil{ 4431.59Skamil pid_t child, wpid; 4441.59Skamil#if defined(TWAIT_HAVE_STATUS) 4451.59Skamil int status; 4461.59Skamil#endif 4471.59Skamil struct ptrace_siginfo info; 4481.61Skre 4491.71Skamil#ifndef PTRACE_ILLEGAL_ASM 4501.71Skamil if (sig == SIGILL) 4511.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 4521.71Skamil#endif 4531.71Skamil 4541.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 4551.114Skamil atf_tc_skip("FP exceptions are not supported"); 4561.114Skamil 4571.59Skamil memset(&info, 0, sizeof(info)); 4581.59Skamil 4591.59Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 4601.59Skamil SYSCALL_REQUIRE((child = fork()) != -1); 4611.59Skamil if (child == 0) { 4621.59Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 4631.59Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 4641.59Skamil 4651.59Skamil DPRINTF("Before executing a trap\n"); 4661.59Skamil switch (sig) { 4671.59Skamil case SIGTRAP: 4681.59Skamil trigger_trap(); 4691.59Skamil break; 4701.59Skamil case SIGSEGV: 4711.59Skamil trigger_segv(); 4721.59Skamil break; 4731.59Skamil case SIGILL: 4741.59Skamil trigger_ill(); 4751.59Skamil break; 4761.59Skamil case SIGFPE: 4771.59Skamil trigger_fpe(); 4781.59Skamil break; 4791.59Skamil case SIGBUS: 4801.59Skamil trigger_bus(); 4811.59Skamil break; 4821.59Skamil default: 4831.59Skamil /* NOTREACHED */ 4841.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4851.59Skamil } 4861.59Skamil 4871.59Skamil /* NOTREACHED */ 4881.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4891.59Skamil } 4901.59Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 4911.59Skamil 4921.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4931.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4941.59Skamil 4951.59Skamil validate_status_stopped(status, sig); 4961.59Skamil 4971.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 4981.61Skre SYSCALL_REQUIRE( 4991.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 5001.59Skamil 5011.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 5021.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 5031.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 5041.61Skre info.psi_siginfo.si_errno); 5051.59Skamil 5061.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 5071.59Skamil switch (sig) { 5081.59Skamil case SIGTRAP: 5091.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 5101.59Skamil break; 5111.59Skamil case SIGSEGV: 5121.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 5131.59Skamil break; 5141.71Skamil case SIGILL: 5151.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 5161.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 5171.71Skamil break; 5181.59Skamil case SIGFPE: 5191.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 5201.59Skamil break; 5211.59Skamil case SIGBUS: 5221.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 5231.59Skamil break; 5241.59Skamil } 5251.59Skamil 5261.59Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 5271.59Skamil 5281.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5291.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 5301.59Skamil 5311.59Skamil validate_status_signaled(status, SIGKILL, 0); 5321.59Skamil 5331.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5341.59Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 5351.59Skamil} 5361.59Skamil 5371.61Skre#define TRACEME_CRASH(test, sig) \ 5381.61SkreATF_TC(test); \ 5391.61SkreATF_TC_HEAD(test, tc) \ 5401.61Skre{ \ 5411.61Skre atf_tc_set_md_var(tc, "descr", \ 5421.61Skre "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \ 5431.61Skre} \ 5441.61Skre \ 5451.61SkreATF_TC_BODY(test, tc) \ 5461.61Skre{ \ 5471.61Skre \ 5481.61Skre traceme_crash(sig); \ 5491.59Skamil} 5501.59Skamil 5511.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP) 5521.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV) 5531.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL) 5541.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE) 5551.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS) 5561.59Skamil 5571.59Skamil/// ---------------------------------------------------------------------------- 5581.59Skamil 5591.59Skamilstatic void 5601.88Skamiltraceme_signalmasked_crash(int sig) 5611.88Skamil{ 5621.89Skamil const int sigval = SIGSTOP; 5631.88Skamil pid_t child, wpid; 5641.88Skamil#if defined(TWAIT_HAVE_STATUS) 5651.88Skamil int status; 5661.88Skamil#endif 5671.88Skamil struct ptrace_siginfo info; 5681.88Skamil sigset_t intmask; 5691.89Skamil struct kinfo_proc2 kp; 5701.89Skamil size_t len = sizeof(kp); 5711.89Skamil 5721.89Skamil int name[6]; 5731.89Skamil const size_t namelen = __arraycount(name); 5741.89Skamil ki_sigset_t kp_sigmask; 5751.88Skamil 5761.88Skamil#ifndef PTRACE_ILLEGAL_ASM 5771.88Skamil if (sig == SIGILL) 5781.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 5791.88Skamil#endif 5801.88Skamil 5811.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 5821.114Skamil atf_tc_skip("FP exceptions are not supported"); 5831.114Skamil 5841.88Skamil memset(&info, 0, sizeof(info)); 5851.88Skamil 5861.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 5871.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 5881.88Skamil if (child == 0) { 5891.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 5901.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 5911.88Skamil 5921.88Skamil sigemptyset(&intmask); 5931.88Skamil sigaddset(&intmask, sig); 5941.88Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 5951.88Skamil 5961.89Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 5971.89Skamil FORKEE_ASSERT(raise(sigval) == 0); 5981.89Skamil 5991.88Skamil DPRINTF("Before executing a trap\n"); 6001.88Skamil switch (sig) { 6011.88Skamil case SIGTRAP: 6021.88Skamil trigger_trap(); 6031.88Skamil break; 6041.88Skamil case SIGSEGV: 6051.88Skamil trigger_segv(); 6061.88Skamil break; 6071.88Skamil case SIGILL: 6081.88Skamil trigger_ill(); 6091.88Skamil break; 6101.88Skamil case SIGFPE: 6111.88Skamil trigger_fpe(); 6121.88Skamil break; 6131.88Skamil case SIGBUS: 6141.88Skamil trigger_bus(); 6151.88Skamil break; 6161.88Skamil default: 6171.88Skamil /* NOTREACHED */ 6181.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 6191.88Skamil } 6201.88Skamil 6211.88Skamil /* NOTREACHED */ 6221.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 6231.88Skamil } 6241.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 6251.88Skamil 6261.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6271.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6281.88Skamil 6291.89Skamil validate_status_stopped(status, sigval); 6301.89Skamil 6311.89Skamil name[0] = CTL_KERN, 6321.89Skamil name[1] = KERN_PROC2, 6331.89Skamil name[2] = KERN_PROC_PID; 6341.89Skamil name[3] = child; 6351.89Skamil name[4] = sizeof(kp); 6361.89Skamil name[5] = 1; 6371.89Skamil 6381.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6391.89Skamil 6401.89Skamil kp_sigmask = kp.p_sigmask; 6411.89Skamil 6421.89Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 6431.89Skamil SYSCALL_REQUIRE( 6441.89Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6451.89Skamil 6461.89Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6471.89Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6481.89Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6491.89Skamil info.psi_siginfo.si_errno); 6501.89Skamil 6511.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 6521.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 6531.89Skamil 6541.89Skamil DPRINTF("Before resuming the child process where it left off and " 6551.89Skamil "without signal to be sent\n"); 6561.89Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 6571.89Skamil 6581.89Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6591.89Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6601.89Skamil 6611.88Skamil validate_status_stopped(status, sig); 6621.88Skamil 6631.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 6641.88Skamil SYSCALL_REQUIRE( 6651.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6661.88Skamil 6671.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6681.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6691.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6701.88Skamil info.psi_siginfo.si_errno); 6711.88Skamil 6721.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6731.89Skamil 6741.89Skamil DPRINTF("kp_sigmask=" 6751.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6761.89Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2], 6771.89Skamil kp_sigmask.__bits[3]); 6781.89Skamil 6791.89Skamil DPRINTF("kp.p_sigmask=" 6801.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6811.89Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 6821.89Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 6831.89Skamil 6841.89Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask))); 6851.89Skamil 6861.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 6871.88Skamil switch (sig) { 6881.88Skamil case SIGTRAP: 6891.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 6901.88Skamil break; 6911.88Skamil case SIGSEGV: 6921.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 6931.88Skamil break; 6941.88Skamil case SIGILL: 6951.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 6961.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 6971.88Skamil break; 6981.88Skamil case SIGFPE: 6991.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 7001.88Skamil break; 7011.88Skamil case SIGBUS: 7021.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 7031.88Skamil break; 7041.88Skamil } 7051.88Skamil 7061.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 7071.88Skamil 7081.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7091.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 7101.88Skamil 7111.88Skamil validate_status_signaled(status, SIGKILL, 0); 7121.88Skamil 7131.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7141.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 7151.88Skamil} 7161.88Skamil 7171.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig) \ 7181.88SkamilATF_TC(test); \ 7191.88SkamilATF_TC_HEAD(test, tc) \ 7201.88Skamil{ \ 7211.88Skamil atf_tc_set_md_var(tc, "descr", \ 7221.88Skamil "Verify masked crash signal " #sig " in a child after " \ 7231.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 7241.88Skamil} \ 7251.88Skamil \ 7261.88SkamilATF_TC_BODY(test, tc) \ 7271.88Skamil{ \ 7281.88Skamil \ 7291.88Skamil traceme_signalmasked_crash(sig); \ 7301.88Skamil} 7311.88Skamil 7321.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP) 7331.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV) 7341.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL) 7351.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE) 7361.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS) 7371.88Skamil 7381.88Skamil/// ---------------------------------------------------------------------------- 7391.88Skamil 7401.88Skamilstatic void 7411.88Skamiltraceme_signalignored_crash(int sig) 7421.88Skamil{ 7431.90Skamil const int sigval = SIGSTOP; 7441.88Skamil pid_t child, wpid; 7451.88Skamil#if defined(TWAIT_HAVE_STATUS) 7461.88Skamil int status; 7471.88Skamil#endif 7481.88Skamil struct sigaction sa; 7491.88Skamil struct ptrace_siginfo info; 7501.90Skamil struct kinfo_proc2 kp; 7511.90Skamil size_t len = sizeof(kp); 7521.90Skamil 7531.90Skamil int name[6]; 7541.90Skamil const size_t namelen = __arraycount(name); 7551.90Skamil ki_sigset_t kp_sigignore; 7561.88Skamil 7571.88Skamil#ifndef PTRACE_ILLEGAL_ASM 7581.88Skamil if (sig == SIGILL) 7591.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 7601.88Skamil#endif 7611.88Skamil 7621.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 7631.114Skamil atf_tc_skip("FP exceptions are not supported"); 7641.114Skamil 7651.88Skamil memset(&info, 0, sizeof(info)); 7661.88Skamil 7671.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 7681.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 7691.88Skamil if (child == 0) { 7701.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 7711.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 7721.88Skamil 7731.88Skamil memset(&sa, 0, sizeof(sa)); 7741.88Skamil sa.sa_handler = SIG_IGN; 7751.88Skamil sigemptyset(&sa.sa_mask); 7761.88Skamil 7771.88Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 7781.88Skamil 7791.90Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 7801.90Skamil FORKEE_ASSERT(raise(sigval) == 0); 7811.90Skamil 7821.88Skamil DPRINTF("Before executing a trap\n"); 7831.88Skamil switch (sig) { 7841.88Skamil case SIGTRAP: 7851.88Skamil trigger_trap(); 7861.88Skamil break; 7871.88Skamil case SIGSEGV: 7881.88Skamil trigger_segv(); 7891.88Skamil break; 7901.88Skamil case SIGILL: 7911.88Skamil trigger_ill(); 7921.88Skamil break; 7931.88Skamil case SIGFPE: 7941.88Skamil trigger_fpe(); 7951.88Skamil break; 7961.88Skamil case SIGBUS: 7971.88Skamil trigger_bus(); 7981.88Skamil break; 7991.88Skamil default: 8001.88Skamil /* NOTREACHED */ 8011.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 8021.88Skamil } 8031.88Skamil 8041.88Skamil /* NOTREACHED */ 8051.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 8061.88Skamil } 8071.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 8081.88Skamil 8091.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8101.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8111.88Skamil 8121.90Skamil validate_status_stopped(status, sigval); 8131.90Skamil 8141.90Skamil name[0] = CTL_KERN, 8151.90Skamil name[1] = KERN_PROC2, 8161.90Skamil name[2] = KERN_PROC_PID; 8171.90Skamil name[3] = child; 8181.90Skamil name[4] = sizeof(kp); 8191.90Skamil name[5] = 1; 8201.90Skamil 8211.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8221.90Skamil 8231.90Skamil kp_sigignore = kp.p_sigignore; 8241.90Skamil 8251.90Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 8261.90Skamil SYSCALL_REQUIRE( 8271.90Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8281.90Skamil 8291.90Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8301.90Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8311.90Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8321.90Skamil info.psi_siginfo.si_errno); 8331.90Skamil 8341.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 8351.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 8361.90Skamil 8371.90Skamil DPRINTF("Before resuming the child process where it left off and " 8381.90Skamil "without signal to be sent\n"); 8391.90Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 8401.90Skamil 8411.90Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8421.90Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8431.90Skamil 8441.88Skamil validate_status_stopped(status, sig); 8451.88Skamil 8461.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 8471.88Skamil SYSCALL_REQUIRE( 8481.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8491.88Skamil 8501.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8511.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8521.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8531.88Skamil info.psi_siginfo.si_errno); 8541.88Skamil 8551.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8561.90Skamil 8571.90Skamil DPRINTF("kp_sigignore=" 8581.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8591.90Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 8601.90Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 8611.90Skamil 8621.90Skamil DPRINTF("kp.p_sigignore=" 8631.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8641.90Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 8651.90Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 8661.90Skamil 8671.90Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore))); 8681.90Skamil 8691.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 8701.88Skamil switch (sig) { 8711.88Skamil case SIGTRAP: 8721.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 8731.88Skamil break; 8741.88Skamil case SIGSEGV: 8751.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 8761.88Skamil break; 8771.88Skamil case SIGILL: 8781.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 8791.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 8801.88Skamil break; 8811.88Skamil case SIGFPE: 8821.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 8831.88Skamil break; 8841.88Skamil case SIGBUS: 8851.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 8861.88Skamil break; 8871.88Skamil } 8881.88Skamil 8891.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 8901.88Skamil 8911.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8921.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8931.88Skamil 8941.88Skamil validate_status_signaled(status, SIGKILL, 0); 8951.88Skamil 8961.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8971.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 8981.88Skamil} 8991.88Skamil 9001.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig) \ 9011.88SkamilATF_TC(test); \ 9021.88SkamilATF_TC_HEAD(test, tc) \ 9031.88Skamil{ \ 9041.88Skamil atf_tc_set_md_var(tc, "descr", \ 9051.88Skamil "Verify ignored crash signal " #sig " in a child after " \ 9061.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 9071.88Skamil} \ 9081.88Skamil \ 9091.88SkamilATF_TC_BODY(test, tc) \ 9101.88Skamil{ \ 9111.88Skamil \ 9121.88Skamil traceme_signalignored_crash(sig); \ 9131.88Skamil} 9141.88Skamil 9151.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP) 9161.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV) 9171.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL) 9181.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE) 9191.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS) 9201.88Skamil 9211.88Skamil/// ---------------------------------------------------------------------------- 9221.88Skamil 9231.88Skamilstatic void 9241.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught) 9251.1Skamil{ 9261.1Skamil const int exitval = 5; 9271.34Skamil const int sigval = SIGSTOP; 9281.1Skamil pid_t child, wpid; 9291.1Skamil struct sigaction sa; 9301.1Skamil#if defined(TWAIT_HAVE_STATUS) 9311.1Skamil int status; 9321.1Skamil#endif 9331.61Skre struct ptrace_siginfo info; 9341.1Skamil 9351.45Skamil memset(&info, 0, sizeof(info)); 9361.45Skamil 9371.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 9381.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 9391.1Skamil if (child == 0) { 9401.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 9411.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 9421.1Skamil 9431.34Skamil sa.sa_handler = sah; 9441.1Skamil sa.sa_flags = SA_SIGINFO; 9451.1Skamil sigemptyset(&sa.sa_mask); 9461.1Skamil 9471.1Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 9481.1Skamil 9491.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 9501.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 9511.1Skamil 9521.34Skamil FORKEE_ASSERT_EQ(*traceme_caught, 1); 9531.1Skamil 9541.13Schristos DPRINTF("Before exiting of the child process\n"); 9551.1Skamil _exit(exitval); 9561.1Skamil } 9571.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 9581.1Skamil 9591.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9601.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9611.1Skamil 9621.1Skamil validate_status_stopped(status, sigval); 9631.1Skamil 9641.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 9651.61Skre SYSCALL_REQUIRE( 9661.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 9671.45Skamil 9681.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 9691.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 9701.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 9711.45Skamil info.psi_siginfo.si_errno); 9721.45Skamil 9731.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 9741.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 9751.45Skamil 9761.13Schristos DPRINTF("Before resuming the child process where it left off and with " 9771.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 9781.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 9791.1Skamil 9801.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9811.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9821.1Skamil 9831.1Skamil validate_status_exited(status, exitval); 9841.1Skamil 9851.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 9861.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 9871.1Skamil} 9881.1Skamil 9891.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig) \ 9901.61SkreATF_TC(test); \ 9911.61SkreATF_TC_HEAD(test, tc) \ 9921.61Skre{ \ 9931.61Skre atf_tc_set_md_var(tc, "descr", \ 9941.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 9951.61Skre "handled correctly and caught by a signal handler"); \ 9961.61Skre} \ 9971.61Skre \ 9981.61Skrestatic int test##_caught = 0; \ 9991.61Skre \ 10001.61Skrestatic void \ 10011.61Skretest##_sighandler(int arg) \ 10021.61Skre{ \ 10031.61Skre FORKEE_ASSERT_EQ(arg, sig); \ 10041.61Skre \ 10051.61Skre ++ test##_caught; \ 10061.61Skre} \ 10071.61Skre \ 10081.61SkreATF_TC_BODY(test, tc) \ 10091.61Skre{ \ 10101.61Skre \ 10111.61Skre traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \ 10121.34Skamil} 10131.34Skamil 10141.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered. 10151.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */ 10161.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP) /* hangup */ 10171.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */ 10181.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */ 10191.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */ 10201.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */ 10211.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */ 10221.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */ 10231.34Skamil 10241.34Skamil/// ---------------------------------------------------------------------------- 10251.34Skamil 10261.35Skamilstatic void 10271.50Skamiltraceme_sendsignal_masked(int sigsent) 10281.50Skamil{ 10291.50Skamil const int exitval = 5; 10301.50Skamil const int sigval = SIGSTOP; 10311.50Skamil pid_t child, wpid; 10321.50Skamil sigset_t set; 10331.50Skamil#if defined(TWAIT_HAVE_STATUS) 10341.50Skamil int status; 10351.50Skamil#endif 10361.61Skre struct ptrace_siginfo info; 10371.50Skamil 10381.50Skamil memset(&info, 0, sizeof(info)); 10391.50Skamil 10401.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 10411.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 10421.50Skamil if (child == 0) { 10431.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 10441.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 10451.50Skamil 10461.50Skamil sigemptyset(&set); 10471.50Skamil sigaddset(&set, sigsent); 10481.50Skamil FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 10491.50Skamil 10501.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 10511.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 10521.50Skamil 10531.50Skamil _exit(exitval); 10541.50Skamil } 10551.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 10561.50Skamil 10571.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10581.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10591.50Skamil 10601.50Skamil validate_status_stopped(status, sigval); 10611.50Skamil 10621.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 10631.61Skre SYSCALL_REQUIRE( 10641.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 10651.50Skamil 10661.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 10671.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 10681.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 10691.50Skamil info.psi_siginfo.si_errno); 10701.50Skamil 10711.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 10721.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 10731.50Skamil 10741.50Skamil DPRINTF("Before resuming the child process where it left off and with " 10751.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 10761.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 10771.50Skamil 10781.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10791.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10801.50Skamil 10811.50Skamil validate_status_exited(status, exitval); 10821.50Skamil 10831.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 10841.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 10851.50Skamil} 10861.50Skamil 10871.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig) \ 10881.61SkreATF_TC(test); \ 10891.61SkreATF_TC_HEAD(test, tc) \ 10901.61Skre{ \ 10911.61Skre atf_tc_set_md_var(tc, "descr", \ 10921.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 10931.61Skre "handled correctly and the signal is masked by SIG_BLOCK"); \ 10941.61Skre} \ 10951.61Skre \ 10961.61SkreATF_TC_BODY(test, tc) \ 10971.61Skre{ \ 10981.61Skre \ 10991.61Skre traceme_sendsignal_masked(sig); \ 11001.50Skamil} 11011.50Skamil 11021.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 11031.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */ 11041.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP) /* hangup */ 11051.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */ 11061.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */ 11071.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */ 11081.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */ 11091.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */ 11101.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */ 11111.50Skamil 11121.50Skamil/// ---------------------------------------------------------------------------- 11131.50Skamil 11141.50Skamilstatic void 11151.50Skamiltraceme_sendsignal_ignored(int sigsent) 11161.50Skamil{ 11171.50Skamil const int exitval = 5; 11181.50Skamil const int sigval = SIGSTOP; 11191.50Skamil pid_t child, wpid; 11201.50Skamil struct sigaction sa; 11211.50Skamil#if defined(TWAIT_HAVE_STATUS) 11221.50Skamil int status; 11231.50Skamil#endif 11241.61Skre struct ptrace_siginfo info; 11251.50Skamil 11261.50Skamil memset(&info, 0, sizeof(info)); 11271.50Skamil 11281.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 11291.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 11301.50Skamil if (child == 0) { 11311.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 11321.61Skre 11331.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 11341.50Skamil 11351.50Skamil memset(&sa, 0, sizeof(sa)); 11361.50Skamil sa.sa_handler = SIG_IGN; 11371.50Skamil sigemptyset(&sa.sa_mask); 11381.50Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 11391.50Skamil 11401.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 11411.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 11421.50Skamil 11431.50Skamil _exit(exitval); 11441.50Skamil } 11451.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 11461.50Skamil 11471.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11481.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11491.50Skamil 11501.50Skamil validate_status_stopped(status, sigval); 11511.50Skamil 11521.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 11531.61Skre SYSCALL_REQUIRE( 11541.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 11551.50Skamil 11561.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 11571.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 11581.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 11591.50Skamil info.psi_siginfo.si_errno); 11601.50Skamil 11611.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 11621.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 11631.50Skamil 11641.50Skamil DPRINTF("Before resuming the child process where it left off and with " 11651.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 11661.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 11671.50Skamil 11681.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11691.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11701.50Skamil 11711.50Skamil validate_status_exited(status, exitval); 11721.50Skamil 11731.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 11741.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 11751.50Skamil} 11761.50Skamil 11771.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig) \ 11781.61SkreATF_TC(test); \ 11791.61SkreATF_TC_HEAD(test, tc) \ 11801.61Skre{ \ 11811.61Skre atf_tc_set_md_var(tc, "descr", \ 11821.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 11831.61Skre "handled correctly and the signal is masked by SIG_IGN"); \ 11841.61Skre} \ 11851.61Skre \ 11861.61SkreATF_TC_BODY(test, tc) \ 11871.61Skre{ \ 11881.61Skre \ 11891.61Skre traceme_sendsignal_ignored(sig); \ 11901.50Skamil} 11911.50Skamil 11921.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 11931.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */ 11941.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP) /* hangup */ 11951.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */ 11961.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */ 11971.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */ 11981.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */ 11991.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */ 12001.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */ 12011.50Skamil 12021.50Skamil/// ---------------------------------------------------------------------------- 12031.50Skamil 12041.50Skamilstatic void 12051.50Skamiltraceme_sendsignal_simple(int sigsent) 12061.1Skamil{ 12071.35Skamil const int sigval = SIGSTOP; 12081.35Skamil int exitval = 0; 12091.1Skamil pid_t child, wpid; 12101.1Skamil#if defined(TWAIT_HAVE_STATUS) 12111.1Skamil int status; 12121.85Skamil int expect_core; 12131.85Skamil 12141.85Skamil switch (sigsent) { 12151.85Skamil case SIGABRT: 12161.85Skamil case SIGTRAP: 12171.85Skamil case SIGBUS: 12181.85Skamil case SIGILL: 12191.85Skamil case SIGFPE: 12201.85Skamil case SIGSEGV: 12211.85Skamil expect_core = 1; 12221.85Skamil break; 12231.85Skamil default: 12241.85Skamil expect_core = 0; 12251.85Skamil break; 12261.85Skamil } 12271.1Skamil#endif 12281.61Skre struct ptrace_siginfo info; 12291.1Skamil 12301.45Skamil memset(&info, 0, sizeof(info)); 12311.45Skamil 12321.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 12331.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 12341.1Skamil if (child == 0) { 12351.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 12361.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 12371.1Skamil 12381.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 12391.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 12401.1Skamil 12411.35Skamil switch (sigsent) { 12421.35Skamil case SIGCONT: 12431.48Skamil case SIGSTOP: 12441.35Skamil _exit(exitval); 12451.35Skamil default: 12461.35Skamil /* NOTREACHED */ 12471.35Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 12481.35Skamil } 12491.1Skamil } 12501.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 12511.1Skamil 12521.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12531.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12541.1Skamil 12551.1Skamil validate_status_stopped(status, sigval); 12561.1Skamil 12571.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 12581.61Skre SYSCALL_REQUIRE( 12591.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 12601.45Skamil 12611.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12621.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 12631.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12641.45Skamil info.psi_siginfo.si_errno); 12651.45Skamil 12661.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12671.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12681.45Skamil 12691.13Schristos DPRINTF("Before resuming the child process where it left off and with " 12701.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 12711.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 12721.1Skamil 12731.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12741.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12751.1Skamil 12761.35Skamil switch (sigsent) { 12771.48Skamil case SIGSTOP: 12781.48Skamil validate_status_stopped(status, sigsent); 12791.48Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 12801.61Skre "child\n"); 12811.48Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 12821.61Skre sizeof(info)) != -1); 12831.48Skamil 12841.48Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12851.48Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 12861.61Skre "si_errno=%#x\n", 12871.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12881.61Skre info.psi_siginfo.si_errno); 12891.48Skamil 12901.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12911.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12921.48Skamil 12931.48Skamil DPRINTF("Before resuming the child process where it left off " 12941.61Skre "and with signal %s to be sent\n", strsignal(sigsent)); 12951.48Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 12961.48Skamil 12971.48Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12981.48Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 12991.61Skre child); 13001.48Skamil /* FALLTHROUGH */ 13011.35Skamil case SIGCONT: 13021.35Skamil validate_status_exited(status, exitval); 13031.35Skamil break; 13041.35Skamil default: 13051.35Skamil validate_status_signaled(status, sigsent, expect_core); 13061.35Skamil break; 13071.35Skamil } 13081.1Skamil 13091.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 13101.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 13111.1Skamil} 13121.1Skamil 13131.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig) \ 13141.61SkreATF_TC(test); \ 13151.61SkreATF_TC_HEAD(test, tc) \ 13161.61Skre{ \ 13171.61Skre atf_tc_set_md_var(tc, "descr", \ 13181.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 13191.61Skre "handled correctly in a child without a signal handler"); \ 13201.61Skre} \ 13211.61Skre \ 13221.61SkreATF_TC_BODY(test, tc) \ 13231.61Skre{ \ 13241.61Skre \ 13251.61Skre traceme_sendsignal_simple(sig); \ 13261.35Skamil} 13271.35Skamil 13281.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/ 13291.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/ 13301.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */ 13311.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP) /* hangup */ 13321.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */ 13331.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */ 13341.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */ 13351.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */ 13361.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */ 13371.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */ 13381.35Skamil 13391.35Skamil/// ---------------------------------------------------------------------------- 13401.35Skamil 13411.37SkamilATF_TC(traceme_pid1_parent); 13421.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc) 13431.37Skamil{ 13441.37Skamil atf_tc_set_md_var(tc, "descr", 13451.37Skamil "Verify that PT_TRACE_ME is not allowed when our parent is PID1"); 13461.37Skamil} 13471.37Skamil 13481.37SkamilATF_TC_BODY(traceme_pid1_parent, tc) 13491.37Skamil{ 13501.37Skamil struct msg_fds parent_child; 13511.37Skamil int exitval_child1 = 1, exitval_child2 = 2; 13521.37Skamil pid_t child1, child2, wpid; 13531.37Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 13541.37Skamil#if defined(TWAIT_HAVE_STATUS) 13551.37Skamil int status; 13561.37Skamil#endif 13571.37Skamil 13581.37Skamil SYSCALL_REQUIRE(msg_open(&parent_child) == 0); 13591.37Skamil 13601.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13611.37Skamil SYSCALL_REQUIRE((child1 = fork()) != -1); 13621.37Skamil if (child1 == 0) { 13631.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13641.37Skamil SYSCALL_REQUIRE((child2 = fork()) != -1); 13651.37Skamil if (child2 != 0) { 13661.37Skamil DPRINTF("Parent process PID=%d, child2's PID=%d\n", 13671.61Skre getpid(), child2); 13681.37Skamil _exit(exitval_child1); 13691.37Skamil } 13701.37Skamil CHILD_FROM_PARENT("exit child1", parent_child, msg); 13711.37Skamil 13721.37Skamil DPRINTF("Assert that our parent is PID1 (initproc)\n"); 13731.37Skamil FORKEE_ASSERT_EQ(getppid(), 1); 13741.37Skamil 13751.37Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 13761.37Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1); 13771.37Skamil SYSCALL_REQUIRE_ERRNO(errno, EPERM); 13781.37Skamil 13791.37Skamil CHILD_TO_PARENT("child2 exiting", parent_child, msg); 13801.37Skamil 13811.37Skamil _exit(exitval_child2); 13821.37Skamil } 13831.37Skamil DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1); 13841.37Skamil 13851.37Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 13861.61Skre TWAIT_REQUIRE_SUCCESS( 13871.61Skre wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1); 13881.37Skamil 13891.37Skamil validate_status_exited(status, exitval_child1); 13901.37Skamil 13911.37Skamil DPRINTF("Notify that child1 is dead\n"); 13921.37Skamil PARENT_TO_CHILD("exit child1", parent_child, msg); 13931.37Skamil 13941.37Skamil DPRINTF("Wait for exiting of child2\n"); 13951.37Skamil PARENT_FROM_CHILD("child2 exiting", parent_child, msg); 13961.37Skamil} 13971.37Skamil 13981.37Skamil/// ---------------------------------------------------------------------------- 13991.37Skamil 14001.40Skamilstatic void 14011.40Skamiltraceme_vfork_raise(int sigval) 14021.40Skamil{ 14031.46Skamil const int exitval = 5, exitval_watcher = 10; 14041.46Skamil pid_t child, parent, watcher, wpid; 14051.46Skamil int rv; 14061.40Skamil#if defined(TWAIT_HAVE_STATUS) 14071.40Skamil int status; 14081.85Skamil 14091.85Skamil /* volatile workarounds GCC -Werror=clobbered */ 14101.85Skamil volatile int expect_core; 14111.85Skamil 14121.85Skamil switch (sigval) { 14131.85Skamil case SIGABRT: 14141.85Skamil case SIGTRAP: 14151.85Skamil case SIGBUS: 14161.85Skamil case SIGILL: 14171.85Skamil case SIGFPE: 14181.85Skamil case SIGSEGV: 14191.85Skamil expect_core = 1; 14201.85Skamil break; 14211.85Skamil default: 14221.85Skamil expect_core = 0; 14231.85Skamil break; 14241.85Skamil } 14251.40Skamil#endif 14261.40Skamil 14271.46Skamil /* 14281.46Skamil * Spawn a dedicated thread to watch for a stopped child and emit 14291.46Skamil * the SIGKILL signal to it. 14301.46Skamil * 14311.46Skamil * vfork(2) might clobber watcher, this means that it's safer and 14321.46Skamil * simpler to reparent this process to initproc and forget about it. 14331.46Skamil */ 14341.46Skamil if (sigval == SIGSTOP) { 14351.46Skamil parent = getpid(); 14361.46Skamil 14371.46Skamil watcher = fork(); 14381.46Skamil ATF_REQUIRE(watcher != 1); 14391.46Skamil if (watcher == 0) { 14401.46Skamil /* Double fork(2) trick to reparent to initproc */ 14411.46Skamil watcher = fork(); 14421.46Skamil FORKEE_ASSERT_NEQ(watcher, -1); 14431.46Skamil if (watcher != 0) 14441.46Skamil _exit(exitval_watcher); 14451.46Skamil 14461.46Skamil child = await_stopped_child(parent); 14471.46Skamil 14481.46Skamil errno = 0; 14491.46Skamil rv = kill(child, SIGKILL); 14501.46Skamil FORKEE_ASSERT_EQ(rv, 0); 14511.46Skamil FORKEE_ASSERT_EQ(errno, 0); 14521.46Skamil 14531.46Skamil /* This exit value will be collected by initproc */ 14541.46Skamil _exit(0); 14551.46Skamil } 14561.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14571.46Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0), 14581.61Skre watcher); 14591.46Skamil 14601.46Skamil validate_status_exited(status, exitval_watcher); 14611.46Skamil 14621.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14631.61Skre TWAIT_REQUIRE_FAILURE(ECHILD, 14641.61Skre wpid = TWAIT_GENERIC(watcher, &status, 0)); 14651.46Skamil } 14661.46Skamil 14671.40Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 14681.40Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 14691.40Skamil if (child == 0) { 14701.40Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 14711.40Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 14721.40Skamil 14731.40Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 14741.40Skamil FORKEE_ASSERT(raise(sigval) == 0); 14751.40Skamil 14761.40Skamil switch (sigval) { 14771.46Skamil case SIGSTOP: 14781.40Skamil case SIGKILL: 14791.40Skamil case SIGABRT: 14801.40Skamil case SIGHUP: 14811.85Skamil case SIGTRAP: 14821.85Skamil case SIGBUS: 14831.85Skamil case SIGILL: 14841.85Skamil case SIGFPE: 14851.85Skamil case SIGSEGV: 14861.40Skamil /* NOTREACHED */ 14871.40Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 14881.70Smrg __unreachable(); 14891.40Skamil default: 14901.40Skamil DPRINTF("Before exiting of the child process\n"); 14911.40Skamil _exit(exitval); 14921.40Skamil } 14931.40Skamil } 14941.40Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 14951.40Skamil 14961.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14971.40Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 14981.40Skamil 14991.40Skamil switch (sigval) { 15001.40Skamil case SIGKILL: 15011.40Skamil case SIGABRT: 15021.40Skamil case SIGHUP: 15031.85Skamil case SIGTRAP: 15041.85Skamil case SIGBUS: 15051.85Skamil case SIGILL: 15061.85Skamil case SIGFPE: 15071.85Skamil case SIGSEGV: 15081.40Skamil validate_status_signaled(status, sigval, expect_core); 15091.40Skamil break; 15101.40Skamil case SIGSTOP: 15111.46Skamil validate_status_signaled(status, SIGKILL, 0); 15121.46Skamil break; 15131.40Skamil case SIGCONT: 15141.47Skamil case SIGTSTP: 15151.47Skamil case SIGTTIN: 15161.47Skamil case SIGTTOU: 15171.40Skamil validate_status_exited(status, exitval); 15181.40Skamil break; 15191.40Skamil default: 15201.40Skamil /* NOTREACHED */ 15211.40Skamil ATF_REQUIRE(0 && "NOT IMPLEMENTED"); 15221.40Skamil break; 15231.40Skamil } 15241.40Skamil 15251.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15261.40Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15271.40Skamil} 15281.40Skamil 15291.61Skre#define TRACEME_VFORK_RAISE(test, sig) \ 15301.61SkreATF_TC(test); \ 15311.61SkreATF_TC_HEAD(test, tc) \ 15321.61Skre{ \ 15331.61Skre atf_tc_set_md_var(tc, "descr", \ 15341.61Skre "Verify PT_TRACE_ME followed by raise of " #sig " in a " \ 15351.61Skre "vfork(2)ed child"); \ 15361.61Skre} \ 15371.61Skre \ 15381.61SkreATF_TC_BODY(test, tc) \ 15391.61Skre{ \ 15401.61Skre \ 15411.61Skre traceme_vfork_raise(sig); \ 15421.40Skamil} 15431.40Skamil 15441.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */ 15451.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */ 15461.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */ 15471.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */ 15481.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */ 15491.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */ 15501.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP) /* hangup */ 15511.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */ 15521.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */ 15531.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */ 15541.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */ 15551.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */ 15561.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */ 15571.40Skamil 15581.40Skamil/// ---------------------------------------------------------------------------- 15591.40Skamil 15601.52Skamilstatic void 15611.52Skamiltraceme_vfork_crash(int sig) 15621.41Skamil{ 15631.41Skamil pid_t child, wpid; 15641.41Skamil#if defined(TWAIT_HAVE_STATUS) 15651.41Skamil int status; 15661.41Skamil#endif 15671.41Skamil 15681.71Skamil#ifndef PTRACE_ILLEGAL_ASM 15691.71Skamil if (sig == SIGILL) 15701.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 15711.71Skamil#endif 15721.71Skamil 15731.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 15741.114Skamil atf_tc_skip("FP exceptions are not supported"); 15751.114Skamil 15761.41Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 15771.41Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 15781.41Skamil if (child == 0) { 15791.41Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 15801.41Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 15811.41Skamil 15821.52Skamil DPRINTF("Before executing a trap\n"); 15831.52Skamil switch (sig) { 15841.52Skamil case SIGTRAP: 15851.52Skamil trigger_trap(); 15861.52Skamil break; 15871.52Skamil case SIGSEGV: 15881.52Skamil trigger_segv(); 15891.52Skamil break; 15901.52Skamil case SIGILL: 15911.52Skamil trigger_ill(); 15921.52Skamil break; 15931.52Skamil case SIGFPE: 15941.52Skamil trigger_fpe(); 15951.52Skamil break; 15961.52Skamil case SIGBUS: 15971.52Skamil trigger_bus(); 15981.52Skamil break; 15991.52Skamil default: 16001.52Skamil /* NOTREACHED */ 16011.52Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16021.52Skamil } 16031.41Skamil 16041.41Skamil /* NOTREACHED */ 16051.41Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16061.41Skamil } 16071.41Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 16081.41Skamil 16091.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16101.41Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 16111.41Skamil 16121.52Skamil validate_status_signaled(status, sig, 1); 16131.41Skamil 16141.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16151.41Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 16161.41Skamil} 16171.41Skamil 16181.61Skre#define TRACEME_VFORK_CRASH(test, sig) \ 16191.61SkreATF_TC(test); \ 16201.61SkreATF_TC_HEAD(test, tc) \ 16211.61Skre{ \ 16221.61Skre atf_tc_set_md_var(tc, "descr", \ 16231.61Skre "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16241.61Skre "vfork(2)ed child"); \ 16251.61Skre} \ 16261.61Skre \ 16271.61SkreATF_TC_BODY(test, tc) \ 16281.61Skre{ \ 16291.61Skre \ 16301.61Skre traceme_vfork_crash(sig); \ 16311.52Skamil} 16321.52Skamil 16331.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP) 16341.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV) 16351.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL) 16361.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE) 16371.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS) 16381.52Skamil 16391.41Skamil/// ---------------------------------------------------------------------------- 16401.41Skamil 16411.92Skamilstatic void 16421.92Skamiltraceme_vfork_signalmasked_crash(int sig) 16431.92Skamil{ 16441.92Skamil pid_t child, wpid; 16451.92Skamil#if defined(TWAIT_HAVE_STATUS) 16461.92Skamil int status; 16471.92Skamil#endif 16481.92Skamil sigset_t intmask; 16491.92Skamil 16501.92Skamil#ifndef PTRACE_ILLEGAL_ASM 16511.92Skamil if (sig == SIGILL) 16521.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 16531.92Skamil#endif 16541.92Skamil 16551.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 16561.114Skamil atf_tc_skip("FP exceptions are not supported"); 16571.114Skamil 16581.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 16591.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 16601.92Skamil if (child == 0) { 16611.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 16621.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 16631.92Skamil 16641.92Skamil sigemptyset(&intmask); 16651.92Skamil sigaddset(&intmask, sig); 16661.92Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 16671.92Skamil 16681.92Skamil DPRINTF("Before executing a trap\n"); 16691.92Skamil switch (sig) { 16701.92Skamil case SIGTRAP: 16711.92Skamil trigger_trap(); 16721.92Skamil break; 16731.92Skamil case SIGSEGV: 16741.92Skamil trigger_segv(); 16751.92Skamil break; 16761.92Skamil case SIGILL: 16771.92Skamil trigger_ill(); 16781.92Skamil break; 16791.92Skamil case SIGFPE: 16801.92Skamil trigger_fpe(); 16811.92Skamil break; 16821.92Skamil case SIGBUS: 16831.92Skamil trigger_bus(); 16841.92Skamil break; 16851.92Skamil default: 16861.92Skamil /* NOTREACHED */ 16871.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16881.92Skamil } 16891.92Skamil 16901.92Skamil /* NOTREACHED */ 16911.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16921.92Skamil } 16931.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 16941.92Skamil 16951.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16961.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 16971.92Skamil 16981.92Skamil validate_status_signaled(status, sig, 1); 16991.92Skamil 17001.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17011.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 17021.92Skamil} 17031.92Skamil 17041.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig) \ 17051.92SkamilATF_TC(test); \ 17061.92SkamilATF_TC_HEAD(test, tc) \ 17071.92Skamil{ \ 17081.92Skamil atf_tc_set_md_var(tc, "descr", \ 17091.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 17101.92Skamil "vfork(2)ed child with a masked signal"); \ 17111.92Skamil} \ 17121.92Skamil \ 17131.92SkamilATF_TC_BODY(test, tc) \ 17141.92Skamil{ \ 17151.92Skamil \ 17161.92Skamil traceme_vfork_signalmasked_crash(sig); \ 17171.92Skamil} 17181.92Skamil 17191.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP) 17201.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV) 17211.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL) 17221.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE) 17231.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS) 17241.92Skamil 17251.92Skamil/// ---------------------------------------------------------------------------- 17261.92Skamil 17271.92Skamilstatic void 17281.92Skamiltraceme_vfork_signalignored_crash(int sig) 17291.92Skamil{ 17301.92Skamil pid_t child, wpid; 17311.92Skamil#if defined(TWAIT_HAVE_STATUS) 17321.92Skamil int status; 17331.92Skamil#endif 17341.92Skamil struct sigaction sa; 17351.92Skamil 17361.92Skamil#ifndef PTRACE_ILLEGAL_ASM 17371.92Skamil if (sig == SIGILL) 17381.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 17391.92Skamil#endif 17401.92Skamil 17411.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 17421.114Skamil atf_tc_skip("FP exceptions are not supported"); 17431.114Skamil 17441.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 17451.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 17461.92Skamil if (child == 0) { 17471.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 17481.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 17491.92Skamil 17501.92Skamil memset(&sa, 0, sizeof(sa)); 17511.92Skamil sa.sa_handler = SIG_IGN; 17521.92Skamil sigemptyset(&sa.sa_mask); 17531.92Skamil 17541.92Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 17551.92Skamil 17561.92Skamil DPRINTF("Before executing a trap\n"); 17571.92Skamil switch (sig) { 17581.92Skamil case SIGTRAP: 17591.92Skamil trigger_trap(); 17601.92Skamil break; 17611.92Skamil case SIGSEGV: 17621.92Skamil trigger_segv(); 17631.92Skamil break; 17641.92Skamil case SIGILL: 17651.92Skamil trigger_ill(); 17661.92Skamil break; 17671.92Skamil case SIGFPE: 17681.92Skamil trigger_fpe(); 17691.92Skamil break; 17701.92Skamil case SIGBUS: 17711.92Skamil trigger_bus(); 17721.92Skamil break; 17731.92Skamil default: 17741.92Skamil /* NOTREACHED */ 17751.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17761.92Skamil } 17771.92Skamil 17781.92Skamil /* NOTREACHED */ 17791.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17801.92Skamil } 17811.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 17821.92Skamil 17831.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17841.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17851.92Skamil 17861.92Skamil validate_status_signaled(status, sig, 1); 17871.92Skamil 17881.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17891.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 17901.92Skamil} 17911.92Skamil 17921.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig) \ 17931.92SkamilATF_TC(test); \ 17941.92SkamilATF_TC_HEAD(test, tc) \ 17951.92Skamil{ \ 17961.92Skamil atf_tc_set_md_var(tc, "descr", \ 17971.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 17981.92Skamil "vfork(2)ed child with ignored signal"); \ 17991.92Skamil} \ 18001.92Skamil \ 18011.92SkamilATF_TC_BODY(test, tc) \ 18021.92Skamil{ \ 18031.92Skamil \ 18041.92Skamil traceme_vfork_signalignored_crash(sig); \ 18051.92Skamil} 18061.92Skamil 18071.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap, 18081.92Skamil SIGTRAP) 18091.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv, 18101.92Skamil SIGSEGV) 18111.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill, 18121.92Skamil SIGILL) 18131.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe, 18141.92Skamil SIGFPE) 18151.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus, 18161.92Skamil SIGBUS) 18171.92Skamil 18181.92Skamil/// ---------------------------------------------------------------------------- 18191.92Skamil 18201.96Skamilstatic void 18211.96Skamiltraceme_vfork_exec(bool masked, bool ignored) 18221.43Skamil{ 18231.43Skamil const int sigval = SIGTRAP; 18241.43Skamil pid_t child, wpid; 18251.43Skamil#if defined(TWAIT_HAVE_STATUS) 18261.43Skamil int status; 18271.43Skamil#endif 18281.96Skamil struct sigaction sa; 18291.61Skre struct ptrace_siginfo info; 18301.96Skamil sigset_t intmask; 18311.96Skamil struct kinfo_proc2 kp; 18321.96Skamil size_t len = sizeof(kp); 18331.96Skamil 18341.96Skamil int name[6]; 18351.96Skamil const size_t namelen = __arraycount(name); 18361.96Skamil ki_sigset_t kp_sigmask; 18371.96Skamil ki_sigset_t kp_sigignore; 18381.43Skamil 18391.43Skamil memset(&info, 0, sizeof(info)); 18401.43Skamil 18411.43Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 18421.43Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 18431.43Skamil if (child == 0) { 18441.43Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 18451.43Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 18461.43Skamil 18471.96Skamil if (masked) { 18481.96Skamil sigemptyset(&intmask); 18491.96Skamil sigaddset(&intmask, sigval); 18501.96Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 18511.96Skamil } 18521.96Skamil 18531.96Skamil if (ignored) { 18541.96Skamil memset(&sa, 0, sizeof(sa)); 18551.96Skamil sa.sa_handler = SIG_IGN; 18561.96Skamil sigemptyset(&sa.sa_mask); 18571.96Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 18581.96Skamil } 18591.96Skamil 18601.43Skamil DPRINTF("Before calling execve(2) from child\n"); 18611.43Skamil execlp("/bin/echo", "/bin/echo", NULL); 18621.43Skamil 18631.43Skamil /* NOTREACHED */ 18641.43Skamil FORKEE_ASSERTX(0 && "Not reached"); 18651.43Skamil } 18661.43Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 18671.43Skamil 18681.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 18691.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 18701.43Skamil 18711.43Skamil validate_status_stopped(status, sigval); 18721.43Skamil 18731.96Skamil name[0] = CTL_KERN, 18741.96Skamil name[1] = KERN_PROC2, 18751.96Skamil name[2] = KERN_PROC_PID; 18761.96Skamil name[3] = getpid(); 18771.96Skamil name[4] = sizeof(kp); 18781.96Skamil name[5] = 1; 18791.96Skamil 18801.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18811.96Skamil 18821.96Skamil if (masked) 18831.96Skamil kp_sigmask = kp.p_sigmask; 18841.96Skamil 18851.96Skamil if (ignored) 18861.96Skamil kp_sigignore = kp.p_sigignore; 18871.96Skamil 18881.96Skamil name[3] = getpid(); 18891.96Skamil 18901.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18911.96Skamil 18921.96Skamil if (masked) { 18931.96Skamil DPRINTF("kp_sigmask=" 18941.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18951.96Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 18961.96Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 18971.96Skamil 18981.96Skamil DPRINTF("kp.p_sigmask=" 18991.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 19001.96Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 19011.96Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 19021.96Skamil 19031.96Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 19041.96Skamil sizeof(kp_sigmask))); 19051.96Skamil } 19061.96Skamil 19071.96Skamil if (ignored) { 19081.96Skamil DPRINTF("kp_sigignore=" 19091.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 19101.96Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 19111.96Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 19121.96Skamil 19131.96Skamil DPRINTF("kp.p_sigignore=" 19141.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 19151.96Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 19161.96Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 19171.96Skamil 19181.96Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 19191.96Skamil sizeof(kp_sigignore))); 19201.96Skamil } 19211.96Skamil 19221.43Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 19231.61Skre SYSCALL_REQUIRE( 19241.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 19251.43Skamil 19261.43Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 19271.43Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 19281.43Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 19291.43Skamil info.psi_siginfo.si_errno); 19301.43Skamil 19311.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 19321.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 19331.43Skamil 19341.43Skamil DPRINTF("Before resuming the child process where it left off and " 19351.43Skamil "without signal to be sent\n"); 19361.43Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 19371.43Skamil 19381.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19391.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 19401.43Skamil 19411.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19421.43Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 19431.43Skamil} 19441.43Skamil 19451.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored) \ 19461.96SkamilATF_TC(test); \ 19471.96SkamilATF_TC_HEAD(test, tc) \ 19481.96Skamil{ \ 19491.96Skamil atf_tc_set_md_var(tc, "descr", \ 19501.96Skamil "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed " \ 19511.96Skamil "child%s%s", masked ? " with masked signal" : "", \ 19521.96Skamil masked ? " with ignored signal" : ""); \ 19531.96Skamil} \ 19541.96Skamil \ 19551.96SkamilATF_TC_BODY(test, tc) \ 19561.96Skamil{ \ 19571.96Skamil \ 19581.96Skamil traceme_vfork_exec(masked, ignored); \ 19591.96Skamil} 19601.96Skamil 19611.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false) 19621.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false) 19631.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true) 19641.96Skamil 19651.43Skamil/// ---------------------------------------------------------------------------- 19661.43Skamil 19671.1Skamil#if defined(TWAIT_HAVE_PID) 19681.51Skamilstatic void 19691.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored) 19701.59Skamil{ 19711.94Skamil const int sigval = SIGSTOP; 19721.59Skamil struct msg_fds parent_tracee, parent_tracer; 19731.59Skamil const int exitval = 10; 19741.59Skamil pid_t tracee, tracer, wpid; 19751.59Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 19761.59Skamil#if defined(TWAIT_HAVE_STATUS) 19771.59Skamil int status; 19781.59Skamil#endif 19791.94Skamil struct sigaction sa; 19801.59Skamil struct ptrace_siginfo info; 19811.94Skamil sigset_t intmask; 19821.94Skamil struct kinfo_proc2 kp; 19831.94Skamil size_t len = sizeof(kp); 19841.94Skamil 19851.94Skamil int name[6]; 19861.94Skamil const size_t namelen = __arraycount(name); 19871.94Skamil ki_sigset_t kp_sigmask; 19881.94Skamil ki_sigset_t kp_sigignore; 19891.61Skre 19901.71Skamil#ifndef PTRACE_ILLEGAL_ASM 19911.71Skamil if (sig == SIGILL) 19921.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 19931.71Skamil#endif 19941.71Skamil 19951.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 19961.114Skamil atf_tc_skip("FP exceptions are not supported"); 19971.114Skamil 19981.59Skamil memset(&info, 0, sizeof(info)); 19991.59Skamil 20001.59Skamil DPRINTF("Spawn tracee\n"); 20011.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 20021.59Skamil tracee = atf_utils_fork(); 20031.59Skamil if (tracee == 0) { 20041.59Skamil // Wait for parent to let us crash 20051.59Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 20061.61Skre 20071.94Skamil if (masked) { 20081.94Skamil sigemptyset(&intmask); 20091.94Skamil sigaddset(&intmask, sig); 20101.94Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 20111.94Skamil } 20121.94Skamil 20131.94Skamil if (ignored) { 20141.94Skamil memset(&sa, 0, sizeof(sa)); 20151.94Skamil sa.sa_handler = SIG_IGN; 20161.94Skamil sigemptyset(&sa.sa_mask); 20171.94Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 20181.94Skamil } 20191.94Skamil 20201.94Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 20211.94Skamil FORKEE_ASSERT(raise(sigval) == 0); 20221.94Skamil 20231.59Skamil DPRINTF("Before executing a trap\n"); 20241.59Skamil switch (sig) { 20251.59Skamil case SIGTRAP: 20261.59Skamil trigger_trap(); 20271.59Skamil break; 20281.59Skamil case SIGSEGV: 20291.59Skamil trigger_segv(); 20301.59Skamil break; 20311.59Skamil case SIGILL: 20321.59Skamil trigger_ill(); 20331.59Skamil break; 20341.59Skamil case SIGFPE: 20351.59Skamil trigger_fpe(); 20361.59Skamil break; 20371.59Skamil case SIGBUS: 20381.59Skamil trigger_bus(); 20391.59Skamil break; 20401.59Skamil default: 20411.59Skamil /* NOTREACHED */ 20421.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20431.59Skamil } 20441.59Skamil 20451.59Skamil /* NOTREACHED */ 20461.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20471.59Skamil } 20481.59Skamil 20491.59Skamil DPRINTF("Spawn debugger\n"); 20501.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 20511.59Skamil tracer = atf_utils_fork(); 20521.59Skamil if (tracer == 0) { 20531.59Skamil /* Fork again and drop parent to reattach to PID 1 */ 20541.59Skamil tracer = atf_utils_fork(); 20551.59Skamil if (tracer != 0) 20561.61Skre _exit(exitval); 20571.59Skamil 20581.59Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 20591.59Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 20601.59Skamil 20611.59Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 20621.59Skamil FORKEE_REQUIRE_SUCCESS( 20631.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20641.59Skamil 20651.59Skamil forkee_status_stopped(status, SIGSTOP); 20661.59Skamil 20671.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20681.94Skamil "traced process\n"); 20691.94Skamil SYSCALL_REQUIRE( 20701.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20711.94Skamil 20721.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20731.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20741.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20751.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20761.94Skamil 20771.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 20781.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 20791.94Skamil 20801.59Skamil /* Resume tracee with PT_CONTINUE */ 20811.59Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 20821.59Skamil 20831.59Skamil /* Inform parent that tracer has attached to tracee */ 20841.59Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 20851.59Skamil 20861.59Skamil /* Wait for parent to tell use that tracee should have exited */ 20871.59Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 20881.59Skamil 20891.59Skamil /* Wait for tracee and assert that it exited */ 20901.59Skamil FORKEE_REQUIRE_SUCCESS( 20911.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20921.59Skamil 20931.94Skamil forkee_status_stopped(status, sigval); 20941.94Skamil 20951.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20961.94Skamil "traced process\n"); 20971.94Skamil SYSCALL_REQUIRE( 20981.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20991.94Skamil 21001.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21011.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21021.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 21031.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 21041.94Skamil 21051.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 21061.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 21071.94Skamil 21081.94Skamil name[0] = CTL_KERN, 21091.94Skamil name[1] = KERN_PROC2, 21101.94Skamil name[2] = KERN_PROC_PID; 21111.94Skamil name[3] = tracee; 21121.94Skamil name[4] = sizeof(kp); 21131.94Skamil name[5] = 1; 21141.94Skamil 21151.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21161.94Skamil 21171.94Skamil if (masked) 21181.94Skamil kp_sigmask = kp.p_sigmask; 21191.94Skamil 21201.94Skamil if (ignored) 21211.94Skamil kp_sigignore = kp.p_sigignore; 21221.94Skamil 21231.94Skamil /* Resume tracee with PT_CONTINUE */ 21241.94Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 21251.94Skamil 21261.94Skamil /* Wait for tracee and assert that it exited */ 21271.94Skamil FORKEE_REQUIRE_SUCCESS( 21281.94Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21291.94Skamil 21301.93Skamil forkee_status_stopped(status, sig); 21311.59Skamil 21321.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 21331.61Skre "traced process\n"); 21341.61Skre SYSCALL_REQUIRE( 21351.61Skre ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 21361.59Skamil 21371.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21381.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21391.61Skre "si_errno=%#x\n", info.psi_siginfo.si_signo, 21401.61Skre info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 21411.59Skamil 21421.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig); 21431.94Skamil 21441.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21451.94Skamil 21461.94Skamil if (masked) { 21471.94Skamil DPRINTF("kp_sigmask=" 21481.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21491.94Skamil PRIx32 "\n", 21501.94Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 21511.94Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 21521.94Skamil 21531.94Skamil DPRINTF("kp.p_sigmask=" 21541.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21551.94Skamil PRIx32 "\n", 21561.94Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 21571.94Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 21581.94Skamil 21591.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask, 21601.94Skamil sizeof(kp_sigmask))); 21611.94Skamil } 21621.94Skamil 21631.94Skamil if (ignored) { 21641.94Skamil DPRINTF("kp_sigignore=" 21651.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21661.94Skamil PRIx32 "\n", 21671.94Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 21681.94Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 21691.94Skamil 21701.94Skamil DPRINTF("kp.p_sigignore=" 21711.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21721.94Skamil PRIx32 "\n", 21731.94Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 21741.94Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 21751.94Skamil 21761.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore, 21771.94Skamil sizeof(kp_sigignore))); 21781.94Skamil } 21791.94Skamil 21801.59Skamil switch (sig) { 21811.59Skamil case SIGTRAP: 21821.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 21831.59Skamil break; 21841.59Skamil case SIGSEGV: 21851.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 21861.59Skamil break; 21871.71Skamil case SIGILL: 21881.113Skamil FORKEE_ASSERT(info.psi_siginfo.si_code >= ILL_ILLOPC && 21891.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 21901.71Skamil break; 21911.59Skamil case SIGFPE: 21921.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 21931.59Skamil break; 21941.59Skamil case SIGBUS: 21951.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 21961.59Skamil break; 21971.59Skamil } 21981.59Skamil 21991.59Skamil FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1); 22001.59Skamil DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME); 22011.93Skamil FORKEE_REQUIRE_SUCCESS( 22021.61Skre wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22031.59Skamil 22041.93Skamil forkee_status_signaled(status, SIGKILL, 0); 22051.59Skamil 22061.71Skamil /* Inform parent that tracer is exiting normally */ 22071.71Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 22081.71Skamil 22091.59Skamil DPRINTF("Before exiting of the tracer process\n"); 22101.59Skamil _exit(0 /* collect by initproc */); 22111.59Skamil } 22121.59Skamil 22131.59Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 22141.59Skamil "calling %s()\n", TWAIT_FNAME); 22151.59Skamil TWAIT_REQUIRE_SUCCESS( 22161.59Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 22171.59Skamil 22181.59Skamil validate_status_exited(status, exitval); 22191.59Skamil 22201.59Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 22211.59Skamil TWAIT_FNAME); 22221.59Skamil TWAIT_REQUIRE_SUCCESS( 22231.59Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 22241.59Skamil 22251.59Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 22261.59Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 22271.59Skamil 22281.59Skamil DPRINTF("Resume the tracee and let it crash\n"); 22291.59Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 22301.59Skamil 22311.59Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 22321.59Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 22331.59Skamil 22341.59Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 22351.59Skamil TWAIT_FNAME); 22361.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22371.59Skamil 22381.59Skamil validate_status_signaled(status, SIGKILL, 0); 22391.59Skamil 22401.71Skamil DPRINTF("Await normal exit of tracer\n"); 22411.71Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 22421.71Skamil 22431.59Skamil msg_close(&parent_tracer); 22441.59Skamil msg_close(&parent_tracee); 22451.59Skamil} 22461.59Skamil 22471.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig) \ 22481.61SkreATF_TC(test); \ 22491.61SkreATF_TC_HEAD(test, tc) \ 22501.61Skre{ \ 22511.61Skre atf_tc_set_md_var(tc, "descr", \ 22521.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22531.94Skamil "the debuggee"); \ 22541.61Skre} \ 22551.61Skre \ 22561.61SkreATF_TC_BODY(test, tc) \ 22571.61Skre{ \ 22581.61Skre \ 22591.94Skamil unrelated_tracer_sees_crash(sig, false, false); \ 22601.59Skamil} 22611.59Skamil 22621.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP) 22631.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV) 22641.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL) 22651.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE) 22661.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS) 22671.94Skamil 22681.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig) \ 22691.94SkamilATF_TC(test); \ 22701.94SkamilATF_TC_HEAD(test, tc) \ 22711.94Skamil{ \ 22721.94Skamil atf_tc_set_md_var(tc, "descr", \ 22731.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22741.94Skamil "the debuggee with masked signal"); \ 22751.94Skamil} \ 22761.94Skamil \ 22771.94SkamilATF_TC_BODY(test, tc) \ 22781.94Skamil{ \ 22791.94Skamil \ 22801.94Skamil unrelated_tracer_sees_crash(sig, true, false); \ 22811.94Skamil} 22821.94Skamil 22831.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22841.94Skamil unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP) 22851.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22861.94Skamil unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV) 22871.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22881.94Skamil unrelated_tracer_sees_signalmasked_crash_ill, SIGILL) 22891.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22901.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE) 22911.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22921.94Skamil unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS) 22931.94Skamil 22941.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig) \ 22951.94SkamilATF_TC(test); \ 22961.94SkamilATF_TC_HEAD(test, tc) \ 22971.94Skamil{ \ 22981.94Skamil atf_tc_set_md_var(tc, "descr", \ 22991.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 23001.94Skamil "the debuggee with signal ignored"); \ 23011.94Skamil} \ 23021.94Skamil \ 23031.94SkamilATF_TC_BODY(test, tc) \ 23041.94Skamil{ \ 23051.94Skamil \ 23061.94Skamil unrelated_tracer_sees_crash(sig, false, true); \ 23071.94Skamil} 23081.94Skamil 23091.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23101.94Skamil unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP) 23111.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23121.94Skamil unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV) 23131.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23141.94Skamil unrelated_tracer_sees_signalignored_crash_ill, SIGILL) 23151.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23161.94Skamil unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE) 23171.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23181.94Skamil unrelated_tracer_sees_signalignored_crash_bus, SIGBUS) 23191.59Skamil#endif 23201.59Skamil 23211.59Skamil/// ---------------------------------------------------------------------------- 23221.59Skamil 23231.59Skamil#if defined(TWAIT_HAVE_PID) 23241.59Skamilstatic void 23251.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated, 23261.67Skamil bool stopped) 23271.1Skamil{ 23281.51Skamil /* 23291.51Skamil * notimeout - disable timeout in await zombie function 23301.51Skamil * unrelated - attach from unrelated tracer reparented to initproc 23311.67Skamil * stopped - attach to a stopped process 23321.51Skamil */ 23331.1Skamil 23341.1Skamil struct msg_fds parent_tracee, parent_tracer; 23351.1Skamil const int exitval_tracee = 5; 23361.1Skamil const int exitval_tracer = 10; 23371.1Skamil pid_t tracee, tracer, wpid; 23381.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 23391.1Skamil#if defined(TWAIT_HAVE_STATUS) 23401.1Skamil int status; 23411.1Skamil#endif 23421.1Skamil 23431.67Skamil /* 23441.67Skamil * Only a subset of options are supported. 23451.67Skamil */ 23461.67Skamil ATF_REQUIRE((!notimeout && !unrelated && !stopped) || 23471.67Skamil (!notimeout && unrelated && !stopped) || 23481.67Skamil (notimeout && !unrelated && !stopped) || 23491.67Skamil (!notimeout && unrelated && stopped)); 23501.67Skamil 23511.13Schristos DPRINTF("Spawn tracee\n"); 23521.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 23531.1Skamil tracee = atf_utils_fork(); 23541.1Skamil if (tracee == 0) { 23551.67Skamil if (stopped) { 23561.67Skamil DPRINTF("Stop self PID %d\n", getpid()); 23571.67Skamil raise(SIGSTOP); 23581.67Skamil } 23591.67Skamil 23601.1Skamil // Wait for parent to let us exit 23611.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 23621.1Skamil _exit(exitval_tracee); 23631.1Skamil } 23641.1Skamil 23651.13Schristos DPRINTF("Spawn debugger\n"); 23661.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 23671.1Skamil tracer = atf_utils_fork(); 23681.1Skamil if (tracer == 0) { 23691.51Skamil if(unrelated) { 23701.51Skamil /* Fork again and drop parent to reattach to PID 1 */ 23711.51Skamil tracer = atf_utils_fork(); 23721.51Skamil if (tracer != 0) 23731.51Skamil _exit(exitval_tracer); 23741.51Skamil } 23751.51Skamil 23761.67Skamil if (stopped) { 23771.67Skamil DPRINTF("Await for a stopped parent PID %d\n", tracee); 23781.67Skamil await_stopped(tracee); 23791.67Skamil } 23801.67Skamil 23811.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 23821.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 23831.1Skamil 23841.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 23851.1Skamil FORKEE_REQUIRE_SUCCESS( 23861.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23871.1Skamil 23881.1Skamil forkee_status_stopped(status, SIGSTOP); 23891.1Skamil 23901.1Skamil /* Resume tracee with PT_CONTINUE */ 23911.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 23921.1Skamil 23931.1Skamil /* Inform parent that tracer has attached to tracee */ 23941.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 23951.1Skamil 23961.1Skamil /* Wait for parent to tell use that tracee should have exited */ 23971.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 23981.1Skamil 23991.1Skamil /* Wait for tracee and assert that it exited */ 24001.1Skamil FORKEE_REQUIRE_SUCCESS( 24011.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24021.1Skamil 24031.1Skamil forkee_status_exited(status, exitval_tracee); 24041.13Schristos DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee); 24051.1Skamil 24061.13Schristos DPRINTF("Before exiting of the tracer process\n"); 24071.51Skamil _exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer); 24081.51Skamil } 24091.51Skamil 24101.51Skamil if (unrelated) { 24111.51Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 24121.51Skamil "calling %s()\n", TWAIT_FNAME); 24131.51Skamil TWAIT_REQUIRE_SUCCESS( 24141.51Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 24151.51Skamil 24161.51Skamil validate_status_exited(status, exitval_tracer); 24171.51Skamil 24181.51Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 24191.51Skamil TWAIT_FNAME); 24201.51Skamil TWAIT_REQUIRE_SUCCESS( 24211.51Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 24221.1Skamil } 24231.1Skamil 24241.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 24251.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 24261.1Skamil 24271.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 24281.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 24291.1Skamil 24301.13Schristos DPRINTF("Detect that tracee is zombie\n"); 24311.51Skamil if (notimeout) 24321.26Skamil await_zombie_raw(tracee, 0); 24331.26Skamil else 24341.26Skamil await_zombie(tracee); 24351.1Skamil 24361.13Schristos DPRINTF("Assert that there is no status about tracee %d - " 24371.1Skamil "Tracer must detect zombie first - calling %s()\n", tracee, 24381.1Skamil TWAIT_FNAME); 24391.1Skamil TWAIT_REQUIRE_SUCCESS( 24401.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 24411.1Skamil 24421.51Skamil if (unrelated) { 24431.51Skamil DPRINTF("Resume the tracer and let it detect exited tracee\n"); 24441.51Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 24451.51Skamil } else { 24461.51Skamil DPRINTF("Tell the tracer child should have exited\n"); 24471.51Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 24481.51Skamil DPRINTF("Wait for tracer to finish its job and exit - calling " 24491.59Skamil "%s()\n", TWAIT_FNAME); 24501.51Skamil 24511.51Skamil DPRINTF("Wait from tracer child to complete waiting for " 24521.59Skamil "tracee\n"); 24531.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 24541.51Skamil tracer); 24551.1Skamil 24561.51Skamil validate_status_exited(status, exitval_tracer); 24571.51Skamil } 24581.1Skamil 24591.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 24601.1Skamil TWAIT_FNAME); 24611.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24621.1Skamil 24631.1Skamil validate_status_exited(status, exitval_tracee); 24641.1Skamil 24651.1Skamil msg_close(&parent_tracer); 24661.1Skamil msg_close(&parent_tracee); 24671.1Skamil} 24681.26Skamil 24691.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent); 24701.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc) 24711.51Skamil{ 24721.51Skamil atf_tc_set_md_var(tc, "descr", 24731.51Skamil "Assert that tracer sees process termination before the parent"); 24741.51Skamil} 24751.51Skamil 24761.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc) 24771.26Skamil{ 24781.26Skamil 24791.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, false, false); 24801.26Skamil} 24811.26Skamil 24821.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates); 24831.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc) 24841.1Skamil{ 24851.1Skamil atf_tc_set_md_var(tc, "descr", 24861.51Skamil "Assert that await_zombie() in attach1 always finds a single " 24871.51Skamil "process and no other error is reported"); 24881.1Skamil} 24891.1Skamil 24901.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc) 24911.1Skamil{ 24921.51Skamil time_t start, end; 24931.51Skamil double diff; 24941.51Skamil unsigned long N = 0; 24951.1Skamil 24961.51Skamil /* 24971.51Skamil * Reuse this test with tracer_sees_terminaton_before_the_parent_raw(). 24981.51Skamil * This test body isn't specific to this race, however it's just good 24991.51Skamil * enough for this purposes, no need to invent a dedicated code flow. 25001.51Skamil */ 25011.1Skamil 25021.51Skamil start = time(NULL); 25031.51Skamil while (true) { 25041.51Skamil DPRINTF("Step: %lu\n", N); 25051.67Skamil tracer_sees_terminaton_before_the_parent_raw(true, false, 25061.67Skamil false); 25071.51Skamil end = time(NULL); 25081.51Skamil diff = difftime(end, start); 25091.51Skamil if (diff >= 5.0) 25101.51Skamil break; 25111.51Skamil ++N; 25121.1Skamil } 25131.51Skamil DPRINTF("Iterations: %lu\n", N); 25141.51Skamil} 25151.1Skamil 25161.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent); 25171.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc) 25181.51Skamil{ 25191.51Skamil atf_tc_set_md_var(tc, "descr", 25201.51Skamil "Assert that tracer sees process termination before the parent"); 25211.51Skamil} 25221.1Skamil 25231.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc) 25241.51Skamil{ 25251.1Skamil 25261.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, false); 25271.67Skamil} 25281.67Skamil 25291.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process); 25301.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc) 25311.67Skamil{ 25321.67Skamil atf_tc_set_md_var(tc, "descr", 25331.67Skamil "Assert that tracer can attach to an unrelated stopped process"); 25341.67Skamil} 25351.67Skamil 25361.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc) 25371.67Skamil{ 25381.67Skamil 25391.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, true); 25401.1Skamil} 25411.1Skamil#endif 25421.1Skamil 25431.51Skamil/// ---------------------------------------------------------------------------- 25441.51Skamil 25451.66Skamilstatic void 25461.66Skamilparent_attach_to_its_child(bool stopped) 25471.1Skamil{ 25481.1Skamil struct msg_fds parent_tracee; 25491.1Skamil const int exitval_tracee = 5; 25501.1Skamil pid_t tracee, wpid; 25511.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 25521.1Skamil#if defined(TWAIT_HAVE_STATUS) 25531.1Skamil int status; 25541.1Skamil#endif 25551.1Skamil 25561.13Schristos DPRINTF("Spawn tracee\n"); 25571.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 25581.1Skamil tracee = atf_utils_fork(); 25591.1Skamil if (tracee == 0) { 25601.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 25611.13Schristos DPRINTF("Parent should now attach to tracee\n"); 25621.1Skamil 25631.66Skamil if (stopped) { 25641.66Skamil DPRINTF("Stop self PID %d\n", getpid()); 25651.66Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 25661.66Skamil } 25671.66Skamil 25681.1Skamil CHILD_FROM_PARENT("Message 2", parent_tracee, msg); 25691.1Skamil /* Wait for message from the parent */ 25701.1Skamil _exit(exitval_tracee); 25711.1Skamil } 25721.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 25731.57Skamil 25741.66Skamil if (stopped) { 25751.66Skamil DPRINTF("Await for a stopped tracee PID %d\n", tracee); 25761.66Skamil await_stopped(tracee); 25771.66Skamil } 25781.66Skamil 25791.13Schristos DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee); 25801.13Schristos SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 25811.1Skamil 25821.13Schristos DPRINTF("Wait for the stopped tracee process with %s()\n", 25831.1Skamil TWAIT_FNAME); 25841.1Skamil TWAIT_REQUIRE_SUCCESS( 25851.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25861.1Skamil 25871.1Skamil validate_status_stopped(status, SIGSTOP); 25881.1Skamil 25891.13Schristos DPRINTF("Resume tracee with PT_CONTINUE\n"); 25901.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 25911.1Skamil 25921.13Schristos DPRINTF("Let the tracee exit now\n"); 25931.1Skamil PARENT_TO_CHILD("Message 2", parent_tracee, msg); 25941.1Skamil 25951.13Schristos DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME); 25961.1Skamil TWAIT_REQUIRE_SUCCESS( 25971.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25981.1Skamil 25991.1Skamil validate_status_exited(status, exitval_tracee); 26001.1Skamil 26011.13Schristos DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME); 26021.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 26031.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0)); 26041.1Skamil 26051.1Skamil msg_close(&parent_tracee); 26061.1Skamil} 26071.1Skamil 26081.66SkamilATF_TC(parent_attach_to_its_child); 26091.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc) 26101.66Skamil{ 26111.66Skamil atf_tc_set_md_var(tc, "descr", 26121.66Skamil "Assert that tracer parent can PT_ATTACH to its child"); 26131.66Skamil} 26141.66Skamil 26151.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc) 26161.66Skamil{ 26171.66Skamil 26181.66Skamil parent_attach_to_its_child(false); 26191.66Skamil} 26201.66Skamil 26211.66SkamilATF_TC(parent_attach_to_its_stopped_child); 26221.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc) 26231.66Skamil{ 26241.66Skamil atf_tc_set_md_var(tc, "descr", 26251.66Skamil "Assert that tracer parent can PT_ATTACH to its stopped child"); 26261.66Skamil} 26271.66Skamil 26281.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc) 26291.66Skamil{ 26301.66Skamil 26311.66Skamil parent_attach_to_its_child(true); 26321.66Skamil} 26331.66Skamil 26341.51Skamil/// ---------------------------------------------------------------------------- 26351.51Skamil 26361.65Skamilstatic void 26371.65Skamilchild_attach_to_its_parent(bool stopped) 26381.1Skamil{ 26391.1Skamil struct msg_fds parent_tracee; 26401.1Skamil const int exitval_tracer = 5; 26411.1Skamil pid_t tracer, wpid; 26421.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 26431.1Skamil#if defined(TWAIT_HAVE_STATUS) 26441.1Skamil int status; 26451.1Skamil#endif 26461.1Skamil 26471.13Schristos DPRINTF("Spawn tracer\n"); 26481.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 26491.1Skamil tracer = atf_utils_fork(); 26501.1Skamil if (tracer == 0) { 26511.1Skamil /* Wait for message from the parent */ 26521.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 26531.1Skamil 26541.65Skamil if (stopped) { 26551.65Skamil DPRINTF("Await for a stopped parent PID %d\n", 26561.65Skamil getppid()); 26571.65Skamil await_stopped(getppid()); 26581.65Skamil } 26591.65Skamil 26601.13Schristos DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n", 26611.1Skamil getppid()); 26621.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1); 26631.1Skamil 26641.13Schristos DPRINTF("Wait for the stopped parent process with %s()\n", 26651.1Skamil TWAIT_FNAME); 26661.1Skamil FORKEE_REQUIRE_SUCCESS( 26671.1Skamil wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid()); 26681.1Skamil 26691.1Skamil forkee_status_stopped(status, SIGSTOP); 26701.1Skamil 26711.13Schristos DPRINTF("Resume parent with PT_DETACH\n"); 26721.1Skamil FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0) 26731.1Skamil != -1); 26741.1Skamil 26751.1Skamil /* Tell parent we are ready */ 26761.1Skamil CHILD_TO_PARENT("Message 1", parent_tracee, msg); 26771.1Skamil 26781.1Skamil _exit(exitval_tracer); 26791.1Skamil } 26801.1Skamil 26811.13Schristos DPRINTF("Wait for the tracer to become ready\n"); 26821.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 26831.65Skamil 26841.65Skamil if (stopped) { 26851.65Skamil DPRINTF("Stop self PID %d\n", getpid()); 26861.65Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 26871.65Skamil } 26881.65Skamil 26891.13Schristos DPRINTF("Allow the tracer to exit now\n"); 26901.1Skamil PARENT_FROM_CHILD("Message 1", parent_tracee, msg); 26911.1Skamil 26921.13Schristos DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME); 26931.1Skamil TWAIT_REQUIRE_SUCCESS( 26941.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 26951.1Skamil 26961.1Skamil validate_status_exited(status, exitval_tracer); 26971.1Skamil 26981.13Schristos DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME); 26991.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 27001.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0)); 27011.1Skamil 27021.1Skamil msg_close(&parent_tracee); 27031.1Skamil} 27041.1Skamil 27051.65SkamilATF_TC(child_attach_to_its_parent); 27061.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc) 27071.65Skamil{ 27081.65Skamil atf_tc_set_md_var(tc, "descr", 27091.65Skamil "Assert that tracer child can PT_ATTACH to its parent"); 27101.65Skamil} 27111.65Skamil 27121.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc) 27131.65Skamil{ 27141.65Skamil 27151.65Skamil child_attach_to_its_parent(false); 27161.65Skamil} 27171.65Skamil 27181.65SkamilATF_TC(child_attach_to_its_stopped_parent); 27191.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc) 27201.65Skamil{ 27211.65Skamil atf_tc_set_md_var(tc, "descr", 27221.65Skamil "Assert that tracer child can PT_ATTACH to its stopped parent"); 27231.65Skamil} 27241.65Skamil 27251.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc) 27261.65Skamil{ 27271.65Skamil /* 27281.65Skamil * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as 27291.65Skamil * this causes a pipe (established from atf-run) to be broken. 27301.65Skamil * atf-run uses this mechanism to monitor whether a test is alive. 27311.65Skamil * 27321.65Skamil * As a workaround spawn this test as a subprocess. 27331.65Skamil */ 27341.65Skamil 27351.65Skamil const int exitval = 15; 27361.65Skamil pid_t child, wpid; 27371.65Skamil#if defined(TWAIT_HAVE_STATUS) 27381.65Skamil int status; 27391.65Skamil#endif 27401.65Skamil 27411.65Skamil SYSCALL_REQUIRE((child = fork()) != -1); 27421.65Skamil if (child == 0) { 27431.65Skamil child_attach_to_its_parent(true); 27441.65Skamil _exit(exitval); 27451.65Skamil } else { 27461.65Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 27471.65Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 27481.65Skamil 27491.65Skamil validate_status_exited(status, exitval); 27501.65Skamil 27511.65Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 27521.65Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 27531.65Skamil } 27541.65Skamil} 27551.65Skamil 27561.51Skamil/// ---------------------------------------------------------------------------- 27571.51Skamil 27581.1Skamil#if defined(TWAIT_HAVE_PID) 27591.1Skamil 27601.51Skamilenum tracee_sees_its_original_parent_type { 27611.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 27621.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 27631.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS 27641.51Skamil}; 27651.51Skamil 27661.51Skamilstatic void 27671.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type) 27681.1Skamil{ 27691.1Skamil struct msg_fds parent_tracer, parent_tracee; 27701.1Skamil const int exitval_tracee = 5; 27711.1Skamil const int exitval_tracer = 10; 27721.1Skamil pid_t parent, tracee, tracer, wpid; 27731.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 27741.1Skamil#if defined(TWAIT_HAVE_STATUS) 27751.1Skamil int status; 27761.1Skamil#endif 27771.51Skamil /* sysctl(3) - kinfo_proc2 */ 27781.51Skamil int name[CTL_MAXNAME]; 27791.51Skamil struct kinfo_proc2 kp; 27801.51Skamil size_t len = sizeof(kp); 27811.51Skamil unsigned int namelen; 27821.51Skamil 27831.51Skamil /* procfs - status */ 27841.51Skamil FILE *fp; 27851.51Skamil struct stat st; 27861.51Skamil const char *fname = "/proc/curproc/status"; 27871.51Skamil char s_executable[MAXPATHLEN]; 27881.51Skamil int s_pid, s_ppid; 27891.51Skamil int rv; 27901.51Skamil 27911.51Skamil if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) { 27921.61Skre SYSCALL_REQUIRE( 27931.61Skre (rv = stat(fname, &st)) == 0 || (errno == ENOENT)); 27941.61Skre if (rv != 0) 27951.51Skamil atf_tc_skip("/proc/curproc/status not found"); 27961.51Skamil } 27971.1Skamil 27981.13Schristos DPRINTF("Spawn tracee\n"); 27991.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 28001.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 28011.1Skamil tracee = atf_utils_fork(); 28021.1Skamil if (tracee == 0) { 28031.1Skamil parent = getppid(); 28041.1Skamil 28051.1Skamil /* Emit message to the parent */ 28061.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 28071.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 28081.1Skamil 28091.51Skamil switch (type) { 28101.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID: 28111.51Skamil FORKEE_ASSERT_EQ(parent, getppid()); 28121.51Skamil break; 28131.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2: 28141.51Skamil namelen = 0; 28151.51Skamil name[namelen++] = CTL_KERN; 28161.51Skamil name[namelen++] = KERN_PROC2; 28171.51Skamil name[namelen++] = KERN_PROC_PID; 28181.51Skamil name[namelen++] = getpid(); 28191.51Skamil name[namelen++] = len; 28201.51Skamil name[namelen++] = 1; 28211.51Skamil 28221.61Skre FORKEE_ASSERT_EQ( 28231.61Skre sysctl(name, namelen, &kp, &len, NULL, 0), 0); 28241.51Skamil FORKEE_ASSERT_EQ(parent, kp.p_ppid); 28251.51Skamil break; 28261.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS: 28271.51Skamil /* 28281.51Skamil * Format: 28291.51Skamil * EXECUTABLE PID PPID ... 28301.51Skamil */ 28311.51Skamil FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL); 28321.51Skamil fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid); 28331.51Skamil FORKEE_ASSERT_EQ(fclose(fp), 0); 28341.51Skamil FORKEE_ASSERT_EQ(parent, s_ppid); 28351.51Skamil break; 28361.51Skamil } 28371.1Skamil 28381.1Skamil _exit(exitval_tracee); 28391.1Skamil } 28401.13Schristos DPRINTF("Wait for child to record its parent identifier (pid)\n"); 28411.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 28421.1Skamil 28431.13Schristos DPRINTF("Spawn debugger\n"); 28441.1Skamil tracer = atf_utils_fork(); 28451.1Skamil if (tracer == 0) { 28461.1Skamil /* No IPC to communicate with the child */ 28471.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 28481.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 28491.1Skamil 28501.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 28511.1Skamil FORKEE_REQUIRE_SUCCESS( 28521.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28531.1Skamil 28541.1Skamil forkee_status_stopped(status, SIGSTOP); 28551.1Skamil 28561.1Skamil /* Resume tracee with PT_CONTINUE */ 28571.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 28581.1Skamil 28591.1Skamil /* Inform parent that tracer has attached to tracee */ 28601.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 28611.1Skamil 28621.1Skamil /* Wait for parent to tell use that tracee should have exited */ 28631.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 28641.1Skamil 28651.1Skamil /* Wait for tracee and assert that it exited */ 28661.1Skamil FORKEE_REQUIRE_SUCCESS( 28671.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28681.1Skamil 28691.1Skamil forkee_status_exited(status, exitval_tracee); 28701.1Skamil 28711.13Schristos DPRINTF("Before exiting of the tracer process\n"); 28721.1Skamil _exit(exitval_tracer); 28731.1Skamil } 28741.1Skamil 28751.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 28761.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 28771.1Skamil 28781.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 28791.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 28801.1Skamil 28811.13Schristos DPRINTF("Detect that tracee is zombie\n"); 28821.1Skamil await_zombie(tracee); 28831.1Skamil 28841.13Schristos DPRINTF("Assert that there is no status about tracee - " 28851.1Skamil "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME); 28861.1Skamil TWAIT_REQUIRE_SUCCESS( 28871.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 28881.1Skamil 28891.13Schristos DPRINTF("Tell the tracer child should have exited\n"); 28901.1Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 28911.1Skamil 28921.13Schristos DPRINTF("Wait from tracer child to complete waiting for tracee\n"); 28931.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 28941.1Skamil tracer); 28951.1Skamil 28961.1Skamil validate_status_exited(status, exitval_tracer); 28971.1Skamil 28981.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 28991.1Skamil TWAIT_FNAME); 29001.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 29011.1Skamil tracee); 29021.1Skamil 29031.1Skamil validate_status_exited(status, exitval_tracee); 29041.1Skamil 29051.1Skamil msg_close(&parent_tracer); 29061.1Skamil msg_close(&parent_tracee); 29071.1Skamil} 29081.1Skamil 29091.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr) \ 29101.61SkreATF_TC(test); \ 29111.61SkreATF_TC_HEAD(test, tc) \ 29121.61Skre{ \ 29131.61Skre atf_tc_set_md_var(tc, "descr", \ 29141.61Skre "Assert that tracee sees its original parent when being traced " \ 29151.61Skre "(check " descr ")"); \ 29161.61Skre} \ 29171.61Skre \ 29181.61SkreATF_TC_BODY(test, tc) \ 29191.61Skre{ \ 29201.61Skre \ 29211.61Skre tracee_sees_its_original_parent(type); \ 29221.1Skamil} 29231.1Skamil 29241.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29251.51Skamil tracee_sees_its_original_parent_getppid, 29261.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 29271.51Skamil "getppid(2)"); 29281.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29291.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2, 29301.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 29311.51Skamil "sysctl(3) and kinfo_proc2"); 29321.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29331.51Skamil tracee_sees_its_original_parent_procfs_status, 29341.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS, 29351.51Skamil "the status file in procfs"); 29361.1Skamil#endif 29371.1Skamil 29381.51Skamil/// ---------------------------------------------------------------------------- 29391.1Skamil 29401.53Skamilstatic void 29411.53Skamileventmask_preserved(int event) 29421.1Skamil{ 29431.1Skamil const int exitval = 5; 29441.1Skamil const int sigval = SIGSTOP; 29451.1Skamil pid_t child, wpid; 29461.1Skamil#if defined(TWAIT_HAVE_STATUS) 29471.1Skamil int status; 29481.1Skamil#endif 29491.1Skamil ptrace_event_t set_event, get_event; 29501.1Skamil const int len = sizeof(ptrace_event_t); 29511.1Skamil 29521.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 29531.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 29541.1Skamil if (child == 0) { 29551.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 29561.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 29571.1Skamil 29581.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 29591.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 29601.1Skamil 29611.13Schristos DPRINTF("Before exiting of the child process\n"); 29621.1Skamil _exit(exitval); 29631.1Skamil } 29641.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 29651.1Skamil 29661.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29671.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29681.1Skamil 29691.1Skamil validate_status_stopped(status, sigval); 29701.1Skamil 29711.53Skamil set_event.pe_set_event = event; 29721.61Skre SYSCALL_REQUIRE( 29731.61Skre ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); 29741.61Skre SYSCALL_REQUIRE( 29751.61Skre ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); 29761.125Skamil DPRINTF("set_event=%#x get_event=%#x\n", set_event.pe_set_event, 29771.125Skamil get_event.pe_set_event); 29781.1Skamil ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); 29791.1Skamil 29801.13Schristos DPRINTF("Before resuming the child process where it left off and " 29811.1Skamil "without signal to be sent\n"); 29821.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 29831.1Skamil 29841.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29851.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29861.1Skamil 29871.1Skamil validate_status_exited(status, exitval); 29881.1Skamil 29891.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29901.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 29911.1Skamil} 29921.1Skamil 29931.61Skre#define EVENTMASK_PRESERVED(test, event) \ 29941.61SkreATF_TC(test); \ 29951.61SkreATF_TC_HEAD(test, tc) \ 29961.61Skre{ \ 29971.61Skre atf_tc_set_md_var(tc, "descr", \ 29981.61Skre "Verify that eventmask " #event " is preserved"); \ 29991.61Skre} \ 30001.61Skre \ 30011.61SkreATF_TC_BODY(test, tc) \ 30021.61Skre{ \ 30031.61Skre \ 30041.61Skre eventmask_preserved(event); \ 30051.1Skamil} 30061.1Skamil 30071.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0) 30081.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK) 30091.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK) 30101.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE) 30111.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE) 30121.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT) 30131.125SkamilEVENTMASK_PRESERVED(eventmask_preserved_posix_spawn, PTRACE_POSIX_SPAWN) 30141.1Skamil 30151.53Skamil/// ---------------------------------------------------------------------------- 30161.1Skamil 30171.28Skamilstatic void 30181.125Skamilfork_body(const char *fn, bool trackspawn, bool trackfork, bool trackvfork, 30191.105Skamil bool trackvforkdone) 30201.1Skamil{ 30211.1Skamil const int exitval = 5; 30221.125Skamil const int exitval2 = 0; /* This matched exit status from /bin/echo */ 30231.1Skamil const int sigval = SIGSTOP; 30241.31Skamil pid_t child, child2 = 0, wpid; 30251.1Skamil#if defined(TWAIT_HAVE_STATUS) 30261.1Skamil int status; 30271.1Skamil#endif 30281.1Skamil ptrace_state_t state; 30291.1Skamil const int slen = sizeof(state); 30301.1Skamil ptrace_event_t event; 30311.1Skamil const int elen = sizeof(event); 30321.1Skamil 30331.124Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 30341.124Skamil 30351.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 30361.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 30371.1Skamil if (child == 0) { 30381.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 30391.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 30401.1Skamil 30411.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 30421.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 30431.1Skamil 30441.125Skamil if (strcmp(fn, "spawn") == 0) { 30451.124Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 30461.124Skamil arg[0], NULL, NULL, arg, NULL), 0); 30471.125Skamil } else { 30481.125Skamil if (strcmp(fn, "fork") == 0) { 30491.125Skamil FORKEE_ASSERT((child2 = fork()) != -1); 30501.125Skamil } else if (strcmp(fn, "vfork") == 0) { 30511.125Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 30521.125Skamil } 30531.1Skamil 30541.124Skamil if (child2 == 0) 30551.124Skamil _exit(exitval2); 30561.124Skamil } 30571.1Skamil FORKEE_REQUIRE_SUCCESS 30581.1Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 30591.1Skamil 30601.1Skamil forkee_status_exited(status, exitval2); 30611.1Skamil 30621.13Schristos DPRINTF("Before exiting of the child process\n"); 30631.1Skamil _exit(exitval); 30641.1Skamil } 30651.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 30661.1Skamil 30671.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 30681.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 30691.1Skamil 30701.1Skamil validate_status_stopped(status, sigval); 30711.1Skamil 30721.125Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 30731.125Skamil trackspawn ? "|PTRACE_POSIX_SPAWN" : "", 30741.61Skre trackfork ? "|PTRACE_FORK" : "", 30751.61Skre trackvfork ? "|PTRACE_VFORK" : "", 30761.61Skre trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 30771.30Skamil event.pe_set_event = 0; 30781.125Skamil if (trackspawn) 30791.125Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 30801.30Skamil if (trackfork) 30811.30Skamil event.pe_set_event |= PTRACE_FORK; 30821.30Skamil if (trackvfork) 30831.30Skamil event.pe_set_event |= PTRACE_VFORK; 30841.30Skamil if (trackvforkdone) 30851.30Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 30861.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 30871.1Skamil 30881.13Schristos DPRINTF("Before resuming the child process where it left off and " 30891.1Skamil "without signal to be sent\n"); 30901.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 30911.1Skamil 30921.29Skamil#if defined(TWAIT_HAVE_PID) 30931.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 30941.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 30951.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 30961.29Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 30971.61Skre child); 30981.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 30991.61Skre child); 31001.1Skamil 31011.29Skamil validate_status_stopped(status, SIGTRAP); 31021.1Skamil 31031.61Skre SYSCALL_REQUIRE( 31041.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 31051.125Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 31061.125Skamil ATF_REQUIRE_EQ( 31071.125Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 31081.125Skamil PTRACE_POSIX_SPAWN); 31091.125Skamil } 31101.125Skamil if (trackfork && strcmp(fn, "fork") == 0) { 31111.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 31121.30Skamil PTRACE_FORK); 31131.30Skamil } 31141.125Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 31151.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 31161.30Skamil PTRACE_VFORK); 31171.30Skamil } 31181.29Skamil 31191.29Skamil child2 = state.pe_other_pid; 31201.30Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 31211.29Skamil 31221.29Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 31231.61Skre "%d\n", TWAIT_FNAME, child2, child); 31241.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 31251.29Skamil child2); 31261.1Skamil 31271.29Skamil validate_status_stopped(status, SIGTRAP); 31281.1Skamil 31291.61Skre SYSCALL_REQUIRE( 31301.61Skre ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 31311.125Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 31321.125Skamil ATF_REQUIRE_EQ( 31331.125Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 31341.125Skamil PTRACE_POSIX_SPAWN); 31351.125Skamil } 31361.125Skamil if (trackfork && strcmp(fn, "fork") == 0) { 31371.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 31381.30Skamil PTRACE_FORK); 31391.30Skamil } 31401.125Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 31411.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 31421.30Skamil PTRACE_VFORK); 31431.30Skamil } 31441.30Skamil 31451.29Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 31461.29Skamil 31471.29Skamil DPRINTF("Before resuming the forkee process where it left off " 31481.29Skamil "and without signal to be sent\n"); 31491.61Skre SYSCALL_REQUIRE( 31501.61Skre ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 31511.29Skamil 31521.29Skamil DPRINTF("Before resuming the child process where it left off " 31531.61Skre "and without signal to be sent\n"); 31541.29Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31551.30Skamil } 31561.30Skamil#endif 31571.30Skamil 31581.125Skamil if (trackvforkdone && strcmp(fn, "vfork") == 0) { 31591.30Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 31601.61Skre child); 31611.61Skre TWAIT_REQUIRE_SUCCESS( 31621.61Skre wpid = TWAIT_GENERIC(child, &status, 0), child); 31631.30Skamil 31641.30Skamil validate_status_stopped(status, SIGTRAP); 31651.30Skamil 31661.61Skre SYSCALL_REQUIRE( 31671.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 31681.30Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 31691.30Skamil 31701.30Skamil child2 = state.pe_other_pid; 31711.30Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 31721.61Skre child2); 31731.30Skamil 31741.30Skamil DPRINTF("Before resuming the child process where it left off " 31751.61Skre "and without signal to be sent\n"); 31761.30Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31771.30Skamil } 31781.29Skamil 31791.30Skamil#if defined(TWAIT_HAVE_PID) 31801.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 31811.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 31821.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 31831.29Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 31841.61Skre "\n", TWAIT_FNAME); 31851.61Skre TWAIT_REQUIRE_SUCCESS( 31861.61Skre wpid = TWAIT_GENERIC(child2, &status, 0), child2); 31871.29Skamil 31881.29Skamil validate_status_exited(status, exitval2); 31891.29Skamil 31901.29Skamil DPRINTF("Before calling %s() for the forkee - expected no " 31911.61Skre "process\n", TWAIT_FNAME); 31921.29Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 31931.29Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 31941.29Skamil } 31951.29Skamil#endif 31961.1Skamil 31971.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 31981.1Skamil "SIGCHLD\n", TWAIT_FNAME); 31991.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 32001.1Skamil 32011.1Skamil validate_status_stopped(status, SIGCHLD); 32021.1Skamil 32031.13Schristos DPRINTF("Before resuming the child process where it left off and " 32041.1Skamil "without signal to be sent\n"); 32051.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 32061.1Skamil 32071.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 32081.1Skamil TWAIT_FNAME); 32091.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 32101.1Skamil 32111.1Skamil validate_status_exited(status, exitval); 32121.1Skamil 32131.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 32141.1Skamil TWAIT_FNAME); 32151.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 32161.1Skamil} 32171.28Skamil 32181.125Skamil#define FORK_TEST(name,fun,tspawn,tfork,tvfork,tvforkdone) \ 32191.61SkreATF_TC(name); \ 32201.61SkreATF_TC_HEAD(name, tc) \ 32211.61Skre{ \ 32221.125Skamil atf_tc_set_md_var(tc, "descr", "Verify " fun "() " \ 32231.125Skamil "called with 0%s%s%s%s in EVENT_MASK", \ 32241.126Skamil tspawn ? "|PTRACE_POSIX_SPAWN" : "", \ 32251.105Skamil tfork ? "|PTRACE_FORK" : "", \ 32261.105Skamil tvfork ? "|PTRACE_VFORK" : "", \ 32271.105Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 32281.61Skre} \ 32291.61Skre \ 32301.61SkreATF_TC_BODY(name, tc) \ 32311.61Skre{ \ 32321.61Skre \ 32331.125Skamil fork_body(fun, tspawn, tfork, tvfork, tvforkdone); \ 32341.32Skamil} 32351.32Skamil 32361.125SkamilFORK_TEST(fork1, "fork", false, false, false, false) 32371.31Skamil#if defined(TWAIT_HAVE_PID) 32381.125SkamilFORK_TEST(fork2, "fork", false, true, false, false) 32391.125SkamilFORK_TEST(fork3, "fork", false, false, true, false) 32401.125SkamilFORK_TEST(fork4, "fork", false, true, true, false) 32411.31Skamil#endif 32421.125SkamilFORK_TEST(fork5, "fork", false, false, false, true) 32431.31Skamil#if defined(TWAIT_HAVE_PID) 32441.125SkamilFORK_TEST(fork6, "fork", false, true, false, true) 32451.125SkamilFORK_TEST(fork7, "fork", false, false, true, true) 32461.125SkamilFORK_TEST(fork8, "fork", false, true, true, true) 32471.125Skamil#endif 32481.125SkamilFORK_TEST(fork9, "fork", true, false, false, false) 32491.125Skamil#if defined(TWAIT_HAVE_PID) 32501.125SkamilFORK_TEST(fork10, "fork", true, true, false, false) 32511.125SkamilFORK_TEST(fork11, "fork", true, false, true, false) 32521.125SkamilFORK_TEST(fork12, "fork", true, true, true, false) 32531.125Skamil#endif 32541.125SkamilFORK_TEST(fork13, "fork", true, false, false, true) 32551.125Skamil#if defined(TWAIT_HAVE_PID) 32561.125SkamilFORK_TEST(fork14, "fork", true, true, false, true) 32571.125SkamilFORK_TEST(fork15, "fork", true, false, true, true) 32581.125SkamilFORK_TEST(fork16, "fork", true, true, true, true) 32591.31Skamil#endif 32601.1Skamil 32611.110Skamil#if TEST_VFORK_ENABLED 32621.125SkamilFORK_TEST(vfork1, "vfork", false, false, false, false) 32631.31Skamil#if defined(TWAIT_HAVE_PID) 32641.125SkamilFORK_TEST(vfork2, "vfork", false, true, false, false) 32651.125SkamilFORK_TEST(vfork3, "vfork", false, false, true, false) 32661.125SkamilFORK_TEST(vfork4, "vfork", false, true, true, false) 32671.31Skamil#endif 32681.125SkamilFORK_TEST(vfork5, "vfork", false, false, false, true) 32691.31Skamil#if defined(TWAIT_HAVE_PID) 32701.125SkamilFORK_TEST(vfork6, "vfork", false, true, false, true) 32711.125SkamilFORK_TEST(vfork7, "vfork", false, false, true, true) 32721.125SkamilFORK_TEST(vfork8, "vfork", false, true, true, true) 32731.31Skamil#endif 32741.125SkamilFORK_TEST(vfork9, "vfork", true, false, false, false) 32751.125Skamil#if defined(TWAIT_HAVE_PID) 32761.125SkamilFORK_TEST(vfork10, "vfork", true, true, false, false) 32771.125SkamilFORK_TEST(vfork11, "vfork", true, false, true, false) 32781.125SkamilFORK_TEST(vfork12, "vfork", true, true, true, false) 32791.110Skamil#endif 32801.125SkamilFORK_TEST(vfork13, "vfork", true, false, false, true) 32811.124Skamil#if defined(TWAIT_HAVE_PID) 32821.125SkamilFORK_TEST(vfork14, "vfork", true, true, false, true) 32831.125SkamilFORK_TEST(vfork15, "vfork", true, false, true, true) 32841.125SkamilFORK_TEST(vfork16, "vfork", true, true, true, true) 32851.124Skamil#endif 32861.125Skamil#endif 32871.125Skamil 32881.125SkamilFORK_TEST(posix_spawn1, "spawn", false, false, false, false) 32891.125SkamilFORK_TEST(posix_spawn2, "spawn", false, true, false, false) 32901.125SkamilFORK_TEST(posix_spawn3, "spawn", false, false, true, false) 32911.125SkamilFORK_TEST(posix_spawn4, "spawn", false, true, true, false) 32921.125SkamilFORK_TEST(posix_spawn5, "spawn", false, false, false, true) 32931.125SkamilFORK_TEST(posix_spawn6, "spawn", false, true, false, true) 32941.125SkamilFORK_TEST(posix_spawn7, "spawn", false, false, true, true) 32951.125SkamilFORK_TEST(posix_spawn8, "spawn", false, true, true, true) 32961.124Skamil#if defined(TWAIT_HAVE_PID) 32971.125SkamilFORK_TEST(posix_spawn9, "spawn", true, false, false, false) 32981.125SkamilFORK_TEST(posix_spawn10, "spawn", true, true, false, false) 32991.125SkamilFORK_TEST(posix_spawn11, "spawn", true, false, true, false) 33001.125SkamilFORK_TEST(posix_spawn12, "spawn", true, true, true, false) 33011.125SkamilFORK_TEST(posix_spawn13, "spawn", true, false, false, true) 33021.125SkamilFORK_TEST(posix_spawn14, "spawn", true, true, false, true) 33031.125SkamilFORK_TEST(posix_spawn15, "spawn", true, false, true, true) 33041.125SkamilFORK_TEST(posix_spawn16, "spawn", true, true, true, true) 33051.124Skamil#endif 33061.124Skamil 33071.54Skamil/// ---------------------------------------------------------------------------- 33081.31Skamil 33091.116Skamil#if defined(TWAIT_HAVE_PID) 33101.116Skamilstatic void 33111.126Skamilfork_detach_forker_body(const char *fn, bool kill_process) 33121.116Skamil{ 33131.116Skamil const int exitval = 5; 33141.126Skamil const int exitval2 = 0; /* Matches exit value from /bin/echo */ 33151.116Skamil const int sigval = SIGSTOP; 33161.116Skamil pid_t child, child2 = 0, wpid; 33171.116Skamil#if defined(TWAIT_HAVE_STATUS) 33181.116Skamil int status; 33191.116Skamil#endif 33201.116Skamil ptrace_state_t state; 33211.116Skamil const int slen = sizeof(state); 33221.116Skamil ptrace_event_t event; 33231.116Skamil const int elen = sizeof(event); 33241.116Skamil 33251.116Skamil int op; 33261.116Skamil 33271.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 33281.116Skamil 33291.116Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 33301.116Skamil SYSCALL_REQUIRE((child = fork()) != -1); 33311.116Skamil if (child == 0) { 33321.116Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 33331.116Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 33341.116Skamil 33351.116Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 33361.116Skamil FORKEE_ASSERT(raise(sigval) == 0); 33371.116Skamil 33381.126Skamil if (strcmp(fn, "spawn") == 0) { 33391.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 33401.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 33411.126Skamil } else { 33421.126Skamil if (strcmp(fn, "fork") == 0) { 33431.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 33441.126Skamil } else { 33451.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 33461.126Skamil } 33471.116Skamil 33481.126Skamil if (child2 == 0) 33491.126Skamil _exit(exitval2); 33501.126Skamil } 33511.116Skamil 33521.116Skamil FORKEE_REQUIRE_SUCCESS 33531.116Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 33541.116Skamil 33551.116Skamil forkee_status_exited(status, exitval2); 33561.116Skamil 33571.116Skamil DPRINTF("Before exiting of the child process\n"); 33581.116Skamil _exit(exitval); 33591.116Skamil } 33601.116Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 33611.116Skamil 33621.116Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 33631.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33641.116Skamil 33651.116Skamil validate_status_stopped(status, sigval); 33661.116Skamil 33671.116Skamil DPRINTF("Set EVENT_MASK for the child %d\n", child); 33681.126Skamil event.pe_set_event = PTRACE_POSIX_SPAWN | PTRACE_FORK | PTRACE_VFORK 33691.126Skamil | PTRACE_VFORK_DONE; 33701.116Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 33711.116Skamil 33721.116Skamil DPRINTF("Before resuming the child process where it left off and " 33731.116Skamil "without signal to be sent\n"); 33741.116Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 33751.116Skamil 33761.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child); 33771.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33781.116Skamil 33791.116Skamil validate_status_stopped(status, SIGTRAP); 33801.116Skamil 33811.116Skamil SYSCALL_REQUIRE( 33821.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 33831.126Skamil 33841.126Skamil if (strcmp(fn, "spawn") == 0) 33851.126Skamil op = PTRACE_POSIX_SPAWN; 33861.126Skamil else if (strcmp(fn, "fork") == 0) 33871.126Skamil op = PTRACE_FORK; 33881.126Skamil else 33891.126Skamil op = PTRACE_VFORK; 33901.126Skamil 33911.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 33921.116Skamil 33931.116Skamil child2 = state.pe_other_pid; 33941.116Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 33951.116Skamil 33961.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 33971.126Skamil strcmp(fn, "vfork") == 0) 33981.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 33991.116Skamil else 34001.116Skamil op = PT_CONTINUE; 34011.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 34021.116Skamil 34031.116Skamil DPRINTF("Before calling %s() for the forkee %d of the child %d\n", 34041.116Skamil TWAIT_FNAME, child2, child); 34051.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 34061.116Skamil 34071.116Skamil validate_status_stopped(status, SIGTRAP); 34081.116Skamil 34091.116Skamil SYSCALL_REQUIRE( 34101.116Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 34111.126Skamil if (strcmp(fn, "spawn") == 0) 34121.126Skamil op = PTRACE_POSIX_SPAWN; 34131.126Skamil else if (strcmp(fn, "fork") == 0) 34141.126Skamil op = PTRACE_FORK; 34151.126Skamil else 34161.126Skamil op = PTRACE_VFORK; 34171.126Skamil 34181.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 34191.116Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 34201.116Skamil 34211.116Skamil DPRINTF("Before resuming the forkee process where it left off " 34221.116Skamil "and without signal to be sent\n"); 34231.116Skamil SYSCALL_REQUIRE( 34241.116Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 34251.116Skamil 34261.126Skamil if (strcmp(fn, "vforkdone") == 0) { 34271.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 34281.116Skamil child); 34291.116Skamil TWAIT_REQUIRE_SUCCESS( 34301.116Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 34311.116Skamil 34321.116Skamil validate_status_stopped(status, SIGTRAP); 34331.116Skamil 34341.116Skamil SYSCALL_REQUIRE( 34351.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 34361.116Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 34371.116Skamil 34381.116Skamil child2 = state.pe_other_pid; 34391.116Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 34401.116Skamil child2); 34411.116Skamil 34421.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 34431.116Skamil DPRINTF("Before resuming the child process where it left off " 34441.116Skamil "and without signal to be sent\n"); 34451.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 34461.116Skamil } 34471.116Skamil 34481.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 34491.116Skamil TWAIT_FNAME); 34501.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 34511.116Skamil 34521.116Skamil validate_status_exited(status, exitval2); 34531.116Skamil 34541.116Skamil DPRINTF("Before calling %s() for the forkee - expected no process\n", 34551.116Skamil TWAIT_FNAME); 34561.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child2, &status, 0)); 34571.116Skamil 34581.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 34591.116Skamil TWAIT_FNAME); 34601.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 34611.116Skamil 34621.116Skamil if (kill_process) { 34631.116Skamil validate_status_signaled(status, SIGKILL, 0); 34641.116Skamil } else { 34651.116Skamil validate_status_exited(status, exitval); 34661.116Skamil } 34671.116Skamil 34681.116Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 34691.116Skamil TWAIT_FNAME); 34701.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 34711.116Skamil} 34721.116Skamil 34731.126Skamil#define FORK_DETACH_FORKER(name,event,kprocess) \ 34741.116SkamilATF_TC(name); \ 34751.116SkamilATF_TC_HEAD(name, tc) \ 34761.116Skamil{ \ 34771.126Skamil atf_tc_set_md_var(tc, "descr", "Verify %s " event, \ 34781.126Skamil kprocess ? "killed" : "detached"); \ 34791.116Skamil} \ 34801.116Skamil \ 34811.116SkamilATF_TC_BODY(name, tc) \ 34821.116Skamil{ \ 34831.116Skamil \ 34841.126Skamil fork_detach_forker_body(event, kprocess); \ 34851.116Skamil} 34861.116Skamil 34871.126SkamilFORK_DETACH_FORKER(posix_spawn_detach_spawner, "spawn", false) 34881.126SkamilFORK_DETACH_FORKER(fork_detach_forker, "fork", false) 34891.116Skamil#if TEST_VFORK_ENABLED 34901.126SkamilFORK_DETACH_FORKER(vfork_detach_vforker, "vfork", false) 34911.126SkamilFORK_DETACH_FORKER(vfork_detach_vforkerdone, "vforkdone", false) 34921.116Skamil#endif 34931.126Skamil 34941.126SkamilFORK_DETACH_FORKER(posix_spawn_kill_spawner, "spawn", true) 34951.126SkamilFORK_DETACH_FORKER(fork_kill_forker, "fork", true) 34961.116Skamil#if TEST_VFORK_ENABLED 34971.126SkamilFORK_DETACH_FORKER(vfork_kill_vforker, "vfork", true) 34981.126SkamilFORK_DETACH_FORKER(vfork_kill_vforkerdone, "vforkdone", true) 34991.116Skamil#endif 35001.116Skamil#endif 35011.116Skamil 35021.116Skamil/// ---------------------------------------------------------------------------- 35031.116Skamil 35041.110Skamil#if TEST_VFORK_ENABLED 35051.108Skamilstatic void 35061.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void)) 35071.108Skamil{ 35081.108Skamil const int exitval = 5; 35091.108Skamil const int exitval2 = 15; 35101.108Skamil pid_t child, child2 = 0, wpid; 35111.108Skamil#if defined(TWAIT_HAVE_STATUS) 35121.108Skamil int status; 35131.108Skamil#endif 35141.108Skamil 35151.108Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 35161.108Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 35171.108Skamil if (child == 0) { 35181.108Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 35191.108Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 35201.108Skamil 35211.108Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 35221.108Skamil 35231.108Skamil if (child2 == 0) 35241.108Skamil _exit(exitval2); 35251.108Skamil 35261.108Skamil FORKEE_REQUIRE_SUCCESS 35271.108Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 35281.108Skamil 35291.108Skamil forkee_status_exited(status, exitval2); 35301.108Skamil 35311.108Skamil DPRINTF("Before exiting of the child process\n"); 35321.108Skamil _exit(exitval); 35331.108Skamil } 35341.108Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 35351.108Skamil 35361.108Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 35371.108Skamil TWAIT_FNAME); 35381.108Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 35391.108Skamil 35401.108Skamil validate_status_exited(status, exitval); 35411.108Skamil 35421.108Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 35431.108Skamil TWAIT_FNAME); 35441.108Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 35451.108Skamil} 35461.108Skamil 35471.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun) \ 35481.108SkamilATF_TC(name); \ 35491.108SkamilATF_TC_HEAD(name, tc) \ 35501.108Skamil{ \ 35511.108Skamil atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) " \ 35521.108Skamil "called from vfork(2)ed child"); \ 35531.108Skamil} \ 35541.108Skamil \ 35551.108SkamilATF_TC_BODY(name, tc) \ 35561.108Skamil{ \ 35571.108Skamil \ 35581.108Skamil traceme_vfork_fork_body(fun); \ 35591.108Skamil} 35601.108Skamil 35611.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork) 35621.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork) 35631.110Skamil#endif 35641.108Skamil 35651.108Skamil/// ---------------------------------------------------------------------------- 35661.108Skamil 35671.54Skamilenum bytes_transfer_type { 35681.54Skamil BYTES_TRANSFER_DATA, 35691.54Skamil BYTES_TRANSFER_DATAIO, 35701.54Skamil BYTES_TRANSFER_TEXT, 35711.54Skamil BYTES_TRANSFER_TEXTIO, 35721.54Skamil BYTES_TRANSFER_AUXV 35731.54Skamil}; 35741.31Skamil 35751.54Skamilstatic int __used 35761.54Skamilbytes_transfer_dummy(int a, int b, int c, int d) 35771.54Skamil{ 35781.54Skamil int e, f, g, h; 35791.1Skamil 35801.54Skamil a *= 4; 35811.54Skamil b += 3; 35821.54Skamil c -= 2; 35831.54Skamil d /= 1; 35841.1Skamil 35851.54Skamil e = strtol("10", NULL, 10); 35861.54Skamil f = strtol("20", NULL, 10); 35871.54Skamil g = strtol("30", NULL, 10); 35881.54Skamil h = strtol("40", NULL, 10); 35891.1Skamil 35901.54Skamil return (a + b * c - d) + (e * f - g / h); 35911.1Skamil} 35921.1Skamil 35931.54Skamilstatic void 35941.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type) 35951.1Skamil{ 35961.1Skamil const int exitval = 5; 35971.1Skamil const int sigval = SIGSTOP; 35981.1Skamil pid_t child, wpid; 35991.54Skamil bool skip = false; 36001.1Skamil 36011.54Skamil int lookup_me = 0; 36021.54Skamil uint8_t lookup_me8 = 0; 36031.54Skamil uint16_t lookup_me16 = 0; 36041.54Skamil uint32_t lookup_me32 = 0; 36051.54Skamil uint64_t lookup_me64 = 0; 36061.1Skamil 36071.54Skamil int magic = 0x13579246; 36081.54Skamil uint8_t magic8 = 0xab; 36091.54Skamil uint16_t magic16 = 0x1234; 36101.54Skamil uint32_t magic32 = 0x98765432; 36111.54Skamil uint64_t magic64 = 0xabcdef0123456789; 36121.1Skamil 36131.54Skamil struct ptrace_io_desc io; 36141.1Skamil#if defined(TWAIT_HAVE_STATUS) 36151.1Skamil int status; 36161.1Skamil#endif 36171.60Skre /* 513 is just enough, for the purposes of ATF it's good enough */ 36181.60Skre AuxInfo ai[513], *aip; 36191.55Schristos 36201.55Schristos ATF_REQUIRE(size < sizeof(ai)); 36211.1Skamil 36221.54Skamil /* Prepare variables for .TEXT transfers */ 36231.54Skamil switch (type) { 36241.54Skamil case BYTES_TRANSFER_TEXT: 36251.54Skamil memcpy(&magic, bytes_transfer_dummy, sizeof(magic)); 36261.54Skamil break; 36271.54Skamil case BYTES_TRANSFER_TEXTIO: 36281.54Skamil switch (size) { 36291.54Skamil case 8: 36301.54Skamil memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8)); 36311.54Skamil break; 36321.54Skamil case 16: 36331.54Skamil memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16)); 36341.54Skamil break; 36351.54Skamil case 32: 36361.54Skamil memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32)); 36371.54Skamil break; 36381.54Skamil case 64: 36391.54Skamil memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64)); 36401.54Skamil break; 36411.54Skamil } 36421.54Skamil break; 36431.54Skamil default: 36441.54Skamil break; 36451.54Skamil } 36461.1Skamil 36471.54Skamil /* Prepare variables for PIOD and AUXV transfers */ 36481.54Skamil switch (type) { 36491.54Skamil case BYTES_TRANSFER_TEXTIO: 36501.54Skamil case BYTES_TRANSFER_DATAIO: 36511.54Skamil io.piod_op = operation; 36521.54Skamil switch (size) { 36531.54Skamil case 8: 36541.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36551.54Skamil (void *)bytes_transfer_dummy : 36561.54Skamil &lookup_me8; 36571.54Skamil io.piod_addr = &lookup_me8; 36581.54Skamil io.piod_len = sizeof(lookup_me8); 36591.54Skamil break; 36601.54Skamil case 16: 36611.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36621.54Skamil (void *)bytes_transfer_dummy : 36631.54Skamil &lookup_me16; 36641.54Skamil io.piod_addr = &lookup_me16; 36651.54Skamil io.piod_len = sizeof(lookup_me16); 36661.54Skamil break; 36671.54Skamil case 32: 36681.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36691.54Skamil (void *)bytes_transfer_dummy : 36701.54Skamil &lookup_me32; 36711.54Skamil io.piod_addr = &lookup_me32; 36721.54Skamil io.piod_len = sizeof(lookup_me32); 36731.54Skamil break; 36741.54Skamil case 64: 36751.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36761.54Skamil (void *)bytes_transfer_dummy : 36771.54Skamil &lookup_me64; 36781.54Skamil io.piod_addr = &lookup_me64; 36791.54Skamil io.piod_len = sizeof(lookup_me64); 36801.54Skamil break; 36811.54Skamil default: 36821.54Skamil break; 36831.54Skamil } 36841.54Skamil break; 36851.54Skamil case BYTES_TRANSFER_AUXV: 36861.54Skamil io.piod_op = operation; 36871.54Skamil io.piod_offs = 0; 36881.54Skamil io.piod_addr = ai; 36891.54Skamil io.piod_len = size; 36901.54Skamil break; 36911.54Skamil default: 36921.54Skamil break; 36931.1Skamil } 36941.1Skamil 36951.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 36961.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 36971.1Skamil if (child == 0) { 36981.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 36991.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 37001.1Skamil 37011.54Skamil switch (type) { 37021.54Skamil case BYTES_TRANSFER_DATA: 37031.54Skamil switch (operation) { 37041.54Skamil case PT_READ_D: 37051.54Skamil case PT_READ_I: 37061.54Skamil lookup_me = magic; 37071.54Skamil break; 37081.54Skamil default: 37091.54Skamil break; 37101.54Skamil } 37111.54Skamil break; 37121.54Skamil case BYTES_TRANSFER_DATAIO: 37131.54Skamil switch (operation) { 37141.54Skamil case PIOD_READ_D: 37151.54Skamil case PIOD_READ_I: 37161.54Skamil switch (size) { 37171.54Skamil case 8: 37181.54Skamil lookup_me8 = magic8; 37191.54Skamil break; 37201.54Skamil case 16: 37211.54Skamil lookup_me16 = magic16; 37221.54Skamil break; 37231.54Skamil case 32: 37241.54Skamil lookup_me32 = magic32; 37251.54Skamil break; 37261.54Skamil case 64: 37271.54Skamil lookup_me64 = magic64; 37281.54Skamil break; 37291.54Skamil default: 37301.54Skamil break; 37311.54Skamil } 37321.54Skamil break; 37331.54Skamil default: 37341.54Skamil break; 37351.54Skamil } 37361.54Skamil default: 37371.54Skamil break; 37381.54Skamil } 37391.54Skamil 37401.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 37411.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 37421.1Skamil 37431.54Skamil /* Handle PIOD and PT separately as operation values overlap */ 37441.54Skamil switch (type) { 37451.54Skamil case BYTES_TRANSFER_DATA: 37461.54Skamil switch (operation) { 37471.54Skamil case PT_WRITE_D: 37481.54Skamil case PT_WRITE_I: 37491.54Skamil FORKEE_ASSERT_EQ(lookup_me, magic); 37501.54Skamil break; 37511.54Skamil default: 37521.54Skamil break; 37531.54Skamil } 37541.54Skamil break; 37551.54Skamil case BYTES_TRANSFER_DATAIO: 37561.54Skamil switch (operation) { 37571.54Skamil case PIOD_WRITE_D: 37581.54Skamil case PIOD_WRITE_I: 37591.54Skamil switch (size) { 37601.54Skamil case 8: 37611.54Skamil FORKEE_ASSERT_EQ(lookup_me8, magic8); 37621.54Skamil break; 37631.54Skamil case 16: 37641.54Skamil FORKEE_ASSERT_EQ(lookup_me16, magic16); 37651.54Skamil break; 37661.54Skamil case 32: 37671.54Skamil FORKEE_ASSERT_EQ(lookup_me32, magic32); 37681.54Skamil break; 37691.54Skamil case 64: 37701.54Skamil FORKEE_ASSERT_EQ(lookup_me64, magic64); 37711.54Skamil break; 37721.54Skamil default: 37731.54Skamil break; 37741.54Skamil } 37751.54Skamil break; 37761.54Skamil default: 37771.54Skamil break; 37781.54Skamil } 37791.54Skamil break; 37801.54Skamil case BYTES_TRANSFER_TEXT: 37811.54Skamil FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy, 37821.54Skamil sizeof(magic)) == 0); 37831.54Skamil break; 37841.54Skamil case BYTES_TRANSFER_TEXTIO: 37851.54Skamil switch (size) { 37861.54Skamil case 8: 37871.54Skamil FORKEE_ASSERT(memcmp(&magic8, 37881.54Skamil bytes_transfer_dummy, 37891.54Skamil sizeof(magic8)) == 0); 37901.54Skamil break; 37911.54Skamil case 16: 37921.54Skamil FORKEE_ASSERT(memcmp(&magic16, 37931.54Skamil bytes_transfer_dummy, 37941.54Skamil sizeof(magic16)) == 0); 37951.54Skamil break; 37961.54Skamil case 32: 37971.54Skamil FORKEE_ASSERT(memcmp(&magic32, 37981.54Skamil bytes_transfer_dummy, 37991.54Skamil sizeof(magic32)) == 0); 38001.54Skamil break; 38011.54Skamil case 64: 38021.54Skamil FORKEE_ASSERT(memcmp(&magic64, 38031.54Skamil bytes_transfer_dummy, 38041.54Skamil sizeof(magic64)) == 0); 38051.54Skamil break; 38061.54Skamil } 38071.54Skamil break; 38081.54Skamil default: 38091.54Skamil break; 38101.54Skamil } 38111.54Skamil 38121.13Schristos DPRINTF("Before exiting of the child process\n"); 38131.1Skamil _exit(exitval); 38141.1Skamil } 38151.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 38161.1Skamil 38171.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38181.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 38191.1Skamil 38201.1Skamil validate_status_stopped(status, sigval); 38211.1Skamil 38221.54Skamil /* Check PaX MPROTECT */ 38231.54Skamil if (!can_we_write_to_text(child)) { 38241.54Skamil switch (type) { 38251.54Skamil case BYTES_TRANSFER_TEXTIO: 38261.54Skamil switch (operation) { 38271.54Skamil case PIOD_WRITE_D: 38281.54Skamil case PIOD_WRITE_I: 38291.54Skamil skip = true; 38301.54Skamil break; 38311.54Skamil default: 38321.54Skamil break; 38331.54Skamil } 38341.54Skamil break; 38351.54Skamil case BYTES_TRANSFER_TEXT: 38361.54Skamil switch (operation) { 38371.54Skamil case PT_WRITE_D: 38381.54Skamil case PT_WRITE_I: 38391.54Skamil skip = true; 38401.54Skamil break; 38411.54Skamil default: 38421.54Skamil break; 38431.54Skamil } 38441.54Skamil break; 38451.54Skamil default: 38461.54Skamil break; 38471.54Skamil } 38481.54Skamil } 38491.1Skamil 38501.54Skamil /* Bailout cleanly killing the child process */ 38511.54Skamil if (skip) { 38521.54Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1); 38531.54Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38541.54Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 38551.54Skamil child); 38561.1Skamil 38571.54Skamil validate_status_signaled(status, SIGKILL, 0); 38581.1Skamil 38591.54Skamil atf_tc_skip("PaX MPROTECT setup prevents writes to .text"); 38601.54Skamil } 38611.1Skamil 38621.54Skamil DPRINTF("Calling operation to transfer bytes between child=%d and " 38631.54Skamil "parent=%d\n", child, getpid()); 38641.1Skamil 38651.54Skamil switch (type) { 38661.54Skamil case BYTES_TRANSFER_TEXTIO: 38671.54Skamil case BYTES_TRANSFER_DATAIO: 38681.54Skamil case BYTES_TRANSFER_AUXV: 38691.54Skamil switch (operation) { 38701.54Skamil case PIOD_WRITE_D: 38711.54Skamil case PIOD_WRITE_I: 38721.54Skamil switch (size) { 38731.54Skamil case 8: 38741.54Skamil lookup_me8 = magic8; 38751.54Skamil break; 38761.54Skamil case 16: 38771.54Skamil lookup_me16 = magic16; 38781.54Skamil break; 38791.54Skamil case 32: 38801.54Skamil lookup_me32 = magic32; 38811.54Skamil break; 38821.54Skamil case 64: 38831.54Skamil lookup_me64 = magic64; 38841.54Skamil break; 38851.54Skamil default: 38861.54Skamil break; 38871.54Skamil } 38881.54Skamil break; 38891.54Skamil default: 38901.54Skamil break; 38911.54Skamil } 38921.54Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); 38931.54Skamil switch (operation) { 38941.54Skamil case PIOD_READ_D: 38951.54Skamil case PIOD_READ_I: 38961.54Skamil switch (size) { 38971.54Skamil case 8: 38981.54Skamil ATF_REQUIRE_EQ(lookup_me8, magic8); 38991.54Skamil break; 39001.54Skamil case 16: 39011.54Skamil ATF_REQUIRE_EQ(lookup_me16, magic16); 39021.54Skamil break; 39031.54Skamil case 32: 39041.54Skamil ATF_REQUIRE_EQ(lookup_me32, magic32); 39051.54Skamil break; 39061.54Skamil case 64: 39071.54Skamil ATF_REQUIRE_EQ(lookup_me64, magic64); 39081.54Skamil break; 39091.54Skamil default: 39101.54Skamil break; 39111.54Skamil } 39121.54Skamil break; 39131.54Skamil case PIOD_READ_AUXV: 39141.54Skamil DPRINTF("Asserting that AUXV length (%zu) is > 0\n", 39151.54Skamil io.piod_len); 39161.54Skamil ATF_REQUIRE(io.piod_len > 0); 39171.54Skamil for (aip = ai; aip->a_type != AT_NULL; aip++) 39181.54Skamil DPRINTF("a_type=%#llx a_v=%#llx\n", 39191.54Skamil (long long int)aip->a_type, 39201.54Skamil (long long int)aip->a_v); 39211.54Skamil break; 39221.54Skamil default: 39231.54Skamil break; 39241.54Skamil } 39251.54Skamil break; 39261.54Skamil case BYTES_TRANSFER_TEXT: 39271.54Skamil switch (operation) { 39281.54Skamil case PT_READ_D: 39291.54Skamil case PT_READ_I: 39301.54Skamil errno = 0; 39311.54Skamil lookup_me = ptrace(operation, child, 39321.54Skamil bytes_transfer_dummy, 0); 39331.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 39341.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 39351.54Skamil break; 39361.54Skamil case PT_WRITE_D: 39371.54Skamil case PT_WRITE_I: 39381.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, 39391.54Skamil bytes_transfer_dummy, magic) 39401.54Skamil != -1); 39411.54Skamil break; 39421.54Skamil default: 39431.54Skamil break; 39441.54Skamil } 39451.54Skamil break; 39461.54Skamil case BYTES_TRANSFER_DATA: 39471.54Skamil switch (operation) { 39481.54Skamil case PT_READ_D: 39491.54Skamil case PT_READ_I: 39501.54Skamil errno = 0; 39511.54Skamil lookup_me = ptrace(operation, child, &lookup_me, 0); 39521.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 39531.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 39541.54Skamil break; 39551.54Skamil case PT_WRITE_D: 39561.54Skamil case PT_WRITE_I: 39571.54Skamil lookup_me = magic; 39581.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me, 39591.54Skamil magic) != -1); 39601.54Skamil break; 39611.54Skamil default: 39621.54Skamil break; 39631.54Skamil } 39641.54Skamil break; 39651.54Skamil default: 39661.54Skamil break; 39671.54Skamil } 39681.1Skamil 39691.13Schristos DPRINTF("Before resuming the child process where it left off and " 39701.1Skamil "without signal to be sent\n"); 39711.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 39721.1Skamil 39731.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39741.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 39751.1Skamil 39761.1Skamil validate_status_exited(status, exitval); 39771.1Skamil 39781.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39791.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 39801.1Skamil} 39811.1Skamil 39821.61Skre#define BYTES_TRANSFER(test, operation, size, type) \ 39831.61SkreATF_TC(test); \ 39841.61SkreATF_TC_HEAD(test, tc) \ 39851.61Skre{ \ 39861.61Skre atf_tc_set_md_var(tc, "descr", \ 39871.61Skre "Verify bytes transfer operation" #operation " and size " #size \ 39881.61Skre " of type " #type); \ 39891.61Skre} \ 39901.61Skre \ 39911.61SkreATF_TC_BODY(test, tc) \ 39921.61Skre{ \ 39931.61Skre \ 39941.61Skre bytes_transfer(operation, size, BYTES_TRANSFER_##type); \ 39951.1Skamil} 39961.1Skamil 39971.54Skamil// DATA 39981.1Skamil 39991.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO) 40001.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO) 40011.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO) 40021.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO) 40031.54Skamil 40041.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO) 40051.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO) 40061.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO) 40071.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO) 40081.54Skamil 40091.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO) 40101.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO) 40111.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO) 40121.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO) 40131.54Skamil 40141.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO) 40151.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO) 40161.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO) 40171.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO) 40181.54Skamil 40191.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA) 40201.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA) 40211.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA) 40221.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA) 40231.54Skamil 40241.54Skamil// TEXT 40251.54Skamil 40261.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO) 40271.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO) 40281.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO) 40291.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO) 40301.54Skamil 40311.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO) 40321.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO) 40331.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO) 40341.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO) 40351.54Skamil 40361.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO) 40371.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO) 40381.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO) 40391.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO) 40401.54Skamil 40411.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO) 40421.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO) 40431.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO) 40441.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO) 40451.54Skamil 40461.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT) 40471.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT) 40481.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT) 40491.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT) 40501.1Skamil 40511.54Skamil// AUXV 40521.1Skamil 40531.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV) 40541.1Skamil 40551.54Skamil/// ---------------------------------------------------------------------------- 40561.1Skamil 40571.101Skamilstatic void 40581.101Skamilbytes_transfer_alignment(const char *operation) 40591.101Skamil{ 40601.101Skamil const int exitval = 5; 40611.101Skamil const int sigval = SIGSTOP; 40621.101Skamil pid_t child, wpid; 40631.101Skamil#if defined(TWAIT_HAVE_STATUS) 40641.101Skamil int status; 40651.101Skamil#endif 40661.101Skamil char *buffer; 40671.101Skamil int vector; 40681.101Skamil size_t len; 40691.101Skamil size_t i; 40701.101Skamil int op; 40711.101Skamil 40721.101Skamil struct ptrace_io_desc io; 40731.101Skamil struct ptrace_siginfo info; 40741.101Skamil 40751.101Skamil memset(&io, 0, sizeof(io)); 40761.101Skamil memset(&info, 0, sizeof(info)); 40771.101Skamil 40781.101Skamil /* Testing misaligned byte transfer crossing page boundaries */ 40791.101Skamil len = sysconf(_SC_PAGESIZE) * 2; 40801.101Skamil buffer = malloc(len); 40811.101Skamil ATF_REQUIRE(buffer != NULL); 40821.101Skamil 40831.101Skamil /* Initialize the buffer with random data */ 40841.101Skamil for (i = 0; i < len; i++) 40851.101Skamil buffer[i] = i & 0xff; 40861.101Skamil 40871.101Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 40881.101Skamil SYSCALL_REQUIRE((child = fork()) != -1); 40891.101Skamil if (child == 0) { 40901.101Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 40911.101Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 40921.101Skamil 40931.101Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 40941.101Skamil FORKEE_ASSERT(raise(sigval) == 0); 40951.101Skamil 40961.101Skamil DPRINTF("Before exiting of the child process\n"); 40971.101Skamil _exit(exitval); 40981.101Skamil } 40991.101Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 41001.101Skamil 41011.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41021.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 41031.101Skamil 41041.101Skamil validate_status_stopped(status, sigval); 41051.101Skamil 41061.101Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 41071.101Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 41081.101Skamil != -1); 41091.101Skamil 41101.101Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 41111.101Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 41121.101Skamil "si_errno=%#x\n", 41131.101Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 41141.101Skamil info.psi_siginfo.si_errno); 41151.101Skamil 41161.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 41171.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 41181.101Skamil 41191.101Skamil if (strcmp(operation, "PT_READ_I") == 0 || 41201.101Skamil strcmp(operation, "PT_READ_D") == 0) { 41211.101Skamil if (strcmp(operation, "PT_READ_I")) 41221.101Skamil op = PT_READ_I; 41231.101Skamil else 41241.101Skamil op = PT_READ_D; 41251.101Skamil 41261.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41271.101Skamil errno = 0; 41281.101Skamil vector = ptrace(op, child, buffer + i, 0); 41291.101Skamil ATF_REQUIRE_EQ(errno, 0); 41301.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 41311.101Skamil } 41321.101Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 41331.101Skamil strcmp(operation, "PT_WRITE_D") == 0) { 41341.101Skamil if (strcmp(operation, "PT_WRITE_I")) 41351.101Skamil op = PT_WRITE_I; 41361.101Skamil else 41371.101Skamil op = PT_WRITE_D; 41381.101Skamil 41391.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41401.101Skamil memcpy(&vector, buffer + i, sizeof(int)); 41411.101Skamil SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector) 41421.101Skamil != -1); 41431.101Skamil } 41441.101Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 41451.101Skamil strcmp(operation, "PIOD_READ_D") == 0) { 41461.101Skamil if (strcmp(operation, "PIOD_READ_I")) 41471.101Skamil op = PIOD_READ_I; 41481.101Skamil else 41491.101Skamil op = PIOD_READ_D; 41501.101Skamil 41511.101Skamil io.piod_op = op; 41521.101Skamil io.piod_addr = &vector; 41531.101Skamil io.piod_len = sizeof(int); 41541.101Skamil 41551.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41561.101Skamil io.piod_offs = buffer + i; 41571.101Skamil 41581.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41591.101Skamil != -1); 41601.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 41611.101Skamil } 41621.101Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 41631.101Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 41641.101Skamil if (strcmp(operation, "PIOD_WRITE_I")) 41651.101Skamil op = PIOD_WRITE_I; 41661.101Skamil else 41671.101Skamil op = PIOD_WRITE_D; 41681.101Skamil 41691.101Skamil io.piod_op = op; 41701.101Skamil io.piod_addr = &vector; 41711.101Skamil io.piod_len = sizeof(int); 41721.101Skamil 41731.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41741.101Skamil io.piod_offs = buffer + i; 41751.101Skamil 41761.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41771.101Skamil != -1); 41781.101Skamil } 41791.101Skamil } else if (strcmp(operation, "PIOD_READ_AUXV") == 0) { 41801.101Skamil io.piod_op = PIOD_READ_AUXV; 41811.101Skamil io.piod_addr = &vector; 41821.101Skamil io.piod_len = sizeof(int); 41831.101Skamil 41841.101Skamil errno = 0; 41851.101Skamil i = 0; 41861.101Skamil /* Read the whole AUXV vector, it has no clear length */ 41871.120Skamil while (io.piod_len > 0) { 41881.101Skamil io.piod_offs = (void *)(intptr_t)i; 41891.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41901.120Skamil != -1 || (io.piod_len == 0 && i > 0)); 41911.101Skamil ++i; 41921.101Skamil } 41931.101Skamil } 41941.101Skamil 41951.101Skamil DPRINTF("Before resuming the child process where it left off " 41961.101Skamil "and without signal to be sent\n"); 41971.101Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 41981.101Skamil 41991.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 42001.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 42011.101Skamil child); 42021.101Skamil 42031.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 42041.101Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 42051.101Skamil} 42061.101Skamil 42071.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation) \ 42081.101SkamilATF_TC(test); \ 42091.101SkamilATF_TC_HEAD(test, tc) \ 42101.101Skamil{ \ 42111.101Skamil atf_tc_set_md_var(tc, "descr", \ 42121.101Skamil "Verify bytes transfer for potentially misaligned " \ 42131.101Skamil "operation " operation); \ 42141.101Skamil} \ 42151.101Skamil \ 42161.101SkamilATF_TC_BODY(test, tc) \ 42171.101Skamil{ \ 42181.101Skamil \ 42191.101Skamil bytes_transfer_alignment(operation); \ 42201.101Skamil} 42211.101Skamil 42221.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I") 42231.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D") 42241.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I") 42251.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D") 42261.101Skamil 42271.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I") 42281.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D") 42291.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I") 42301.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D") 42311.101Skamil 42321.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV") 42331.101Skamil 42341.101Skamil/// ---------------------------------------------------------------------------- 42351.101Skamil 42361.115Skamilstatic void 42371.115Skamilbytes_transfer_eof(const char *operation) 42381.115Skamil{ 42391.115Skamil const int exitval = 5; 42401.115Skamil const int sigval = SIGSTOP; 42411.115Skamil pid_t child, wpid; 42421.115Skamil#if defined(TWAIT_HAVE_STATUS) 42431.115Skamil int status; 42441.115Skamil#endif 42451.115Skamil FILE *fp; 42461.115Skamil char *p; 42471.115Skamil int vector; 42481.115Skamil int op; 42491.115Skamil 42501.115Skamil struct ptrace_io_desc io; 42511.115Skamil struct ptrace_siginfo info; 42521.115Skamil 42531.115Skamil memset(&io, 0, sizeof(io)); 42541.115Skamil memset(&info, 0, sizeof(info)); 42551.115Skamil 42561.115Skamil vector = 0; 42571.115Skamil 42581.115Skamil fp = tmpfile(); 42591.115Skamil ATF_REQUIRE(fp != NULL); 42601.115Skamil 42611.115Skamil p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0); 42621.115Skamil ATF_REQUIRE(p != MAP_FAILED); 42631.115Skamil 42641.115Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 42651.115Skamil SYSCALL_REQUIRE((child = fork()) != -1); 42661.115Skamil if (child == 0) { 42671.115Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 42681.115Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 42691.115Skamil 42701.115Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 42711.115Skamil FORKEE_ASSERT(raise(sigval) == 0); 42721.115Skamil 42731.115Skamil DPRINTF("Before exiting of the child process\n"); 42741.115Skamil _exit(exitval); 42751.115Skamil } 42761.115Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 42771.115Skamil 42781.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 42791.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 42801.115Skamil 42811.115Skamil validate_status_stopped(status, sigval); 42821.115Skamil 42831.115Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 42841.115Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 42851.115Skamil != -1); 42861.115Skamil 42871.115Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 42881.115Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 42891.115Skamil "si_errno=%#x\n", 42901.115Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 42911.115Skamil info.psi_siginfo.si_errno); 42921.115Skamil 42931.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 42941.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 42951.115Skamil 42961.115Skamil if (strcmp(operation, "PT_READ_I") == 0 || 42971.115Skamil strcmp(operation, "PT_READ_D") == 0) { 42981.115Skamil if (strcmp(operation, "PT_READ_I")) 42991.115Skamil op = PT_READ_I; 43001.115Skamil else 43011.115Skamil op = PT_READ_D; 43021.115Skamil 43031.115Skamil errno = 0; 43041.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, 0) == -1); 43051.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43061.115Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 43071.115Skamil strcmp(operation, "PT_WRITE_D") == 0) { 43081.115Skamil if (strcmp(operation, "PT_WRITE_I")) 43091.115Skamil op = PT_WRITE_I; 43101.115Skamil else 43111.115Skamil op = PT_WRITE_D; 43121.115Skamil 43131.115Skamil errno = 0; 43141.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, vector) == -1); 43151.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43161.115Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 43171.115Skamil strcmp(operation, "PIOD_READ_D") == 0) { 43181.115Skamil if (strcmp(operation, "PIOD_READ_I")) 43191.115Skamil op = PIOD_READ_I; 43201.115Skamil else 43211.115Skamil op = PIOD_READ_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 } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 43321.115Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 43331.115Skamil if (strcmp(operation, "PIOD_WRITE_I")) 43341.115Skamil op = PIOD_WRITE_I; 43351.115Skamil else 43361.115Skamil op = PIOD_WRITE_D; 43371.115Skamil 43381.115Skamil io.piod_op = op; 43391.115Skamil io.piod_addr = &vector; 43401.115Skamil io.piod_len = sizeof(int); 43411.115Skamil io.piod_offs = p; 43421.115Skamil 43431.115Skamil errno = 0; 43441.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 43451.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43461.115Skamil } 43471.115Skamil 43481.115Skamil DPRINTF("Before resuming the child process where it left off " 43491.115Skamil "and without signal to be sent\n"); 43501.115Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 43511.115Skamil 43521.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43531.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 43541.115Skamil child); 43551.115Skamil 43561.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43571.115Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 43581.115Skamil} 43591.115Skamil 43601.115Skamil#define BYTES_TRANSFER_EOF(test, operation) \ 43611.115SkamilATF_TC(test); \ 43621.115SkamilATF_TC_HEAD(test, tc) \ 43631.115Skamil{ \ 43641.115Skamil atf_tc_set_md_var(tc, "descr", \ 43651.115Skamil "Verify bytes EOF byte transfer for the " operation \ 43661.115Skamil " operation"); \ 43671.115Skamil} \ 43681.115Skamil \ 43691.115SkamilATF_TC_BODY(test, tc) \ 43701.115Skamil{ \ 43711.115Skamil \ 43721.115Skamil bytes_transfer_eof(operation); \ 43731.115Skamil} 43741.115Skamil 43751.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_i, "PT_READ_I") 43761.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_d, "PT_READ_D") 43771.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_i, "PT_WRITE_I") 43781.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_d, "PT_WRITE_D") 43791.115Skamil 43801.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_i, "PIOD_READ_I") 43811.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_d, "PIOD_READ_D") 43821.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_i, "PIOD_WRITE_I") 43831.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_d, "PIOD_WRITE_D") 43841.115Skamil 43851.115Skamil/// ---------------------------------------------------------------------------- 43861.115Skamil 43871.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS) 43881.72Skamilstatic void 43891.72Skamilaccess_regs(const char *regset, const char *aux) 43901.1Skamil{ 43911.1Skamil const int exitval = 5; 43921.1Skamil const int sigval = SIGSTOP; 43931.1Skamil pid_t child, wpid; 43941.1Skamil#if defined(TWAIT_HAVE_STATUS) 43951.1Skamil int status; 43961.1Skamil#endif 43971.72Skamil#if defined(HAVE_GPREGS) 43981.72Skamil struct reg gpr; 43991.76Sscole register_t rgstr; 44001.1Skamil#endif 44011.72Skamil#if defined(HAVE_FPREGS) 44021.72Skamil struct fpreg fpr; 44031.1Skamil#endif 44041.76Sscole 44051.72Skamil#if !defined(HAVE_GPREGS) 44061.72Skamil if (strcmp(regset, "regs") == 0) 44071.72Skamil atf_tc_fail("Impossible test scenario!"); 44081.1Skamil#endif 44091.1Skamil 44101.72Skamil#if !defined(HAVE_FPREGS) 44111.72Skamil if (strcmp(regset, "fpregs") == 0) 44121.72Skamil atf_tc_fail("Impossible test scenario!"); 44131.1Skamil#endif 44141.1Skamil 44151.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 44161.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 44171.1Skamil if (child == 0) { 44181.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 44191.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 44201.1Skamil 44211.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 44221.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 44231.1Skamil 44241.13Schristos DPRINTF("Before exiting of the child process\n"); 44251.1Skamil _exit(exitval); 44261.1Skamil } 44271.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 44281.1Skamil 44291.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44301.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44311.1Skamil 44321.1Skamil validate_status_stopped(status, sigval); 44331.1Skamil 44341.1Skamil#if defined(HAVE_GPREGS) 44351.72Skamil if (strcmp(regset, "regs") == 0) { 44361.72Skamil DPRINTF("Call GETREGS for the child process\n"); 44371.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1); 44381.72Skamil 44391.72Skamil if (strcmp(aux, "none") == 0) { 44401.72Skamil DPRINTF("Retrieved registers\n"); 44411.72Skamil } else if (strcmp(aux, "pc") == 0) { 44421.72Skamil rgstr = PTRACE_REG_PC(&gpr); 44431.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44441.72Skamil } else if (strcmp(aux, "set_pc") == 0) { 44451.72Skamil rgstr = PTRACE_REG_PC(&gpr); 44461.72Skamil PTRACE_REG_SET_PC(&gpr, rgstr); 44471.72Skamil } else if (strcmp(aux, "sp") == 0) { 44481.72Skamil rgstr = PTRACE_REG_SP(&gpr); 44491.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44501.72Skamil } else if (strcmp(aux, "intrv") == 0) { 44511.72Skamil rgstr = PTRACE_REG_INTRV(&gpr); 44521.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44531.72Skamil } else if (strcmp(aux, "setregs") == 0) { 44541.72Skamil DPRINTF("Call SETREGS for the child process\n"); 44551.72Skamil SYSCALL_REQUIRE( 44561.72Skamil ptrace(PT_GETREGS, child, &gpr, 0) != -1); 44571.72Skamil } 44581.72Skamil } 44591.1Skamil#endif 44601.1Skamil 44611.72Skamil#if defined(HAVE_FPREGS) 44621.72Skamil if (strcmp(regset, "fpregs") == 0) { 44631.72Skamil DPRINTF("Call GETFPREGS for the child process\n"); 44641.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1); 44651.72Skamil 44661.72Skamil if (strcmp(aux, "getfpregs") == 0) { 44671.72Skamil DPRINTF("Retrieved FP registers\n"); 44681.72Skamil } else if (strcmp(aux, "setfpregs") == 0) { 44691.72Skamil DPRINTF("Call SETFPREGS for the child\n"); 44701.72Skamil SYSCALL_REQUIRE( 44711.72Skamil ptrace(PT_SETFPREGS, child, &fpr, 0) != -1); 44721.72Skamil } 44731.1Skamil } 44741.1Skamil#endif 44751.1Skamil 44761.13Schristos DPRINTF("Before resuming the child process where it left off and " 44771.1Skamil "without signal to be sent\n"); 44781.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 44791.1Skamil 44801.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44811.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44821.1Skamil 44831.1Skamil validate_status_exited(status, exitval); 44841.1Skamil 44851.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44861.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 44871.1Skamil} 44881.1Skamil 44891.72Skamil#define ACCESS_REGS(test, regset, aux) \ 44901.72SkamilATF_TC(test); \ 44911.72SkamilATF_TC_HEAD(test, tc) \ 44921.72Skamil{ \ 44931.72Skamil atf_tc_set_md_var(tc, "descr", \ 44941.72Skamil "Verify " regset " with auxiliary operation: " aux); \ 44951.72Skamil} \ 44961.72Skamil \ 44971.72SkamilATF_TC_BODY(test, tc) \ 44981.72Skamil{ \ 44991.72Skamil \ 45001.72Skamil access_regs(regset, aux); \ 45011.1Skamil} 45021.1Skamil#endif 45031.1Skamil 45041.72Skamil#if defined(HAVE_GPREGS) 45051.72SkamilACCESS_REGS(access_regs1, "regs", "none") 45061.72SkamilACCESS_REGS(access_regs2, "regs", "pc") 45071.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc") 45081.72SkamilACCESS_REGS(access_regs4, "regs", "sp") 45091.72SkamilACCESS_REGS(access_regs5, "regs", "intrv") 45101.72SkamilACCESS_REGS(access_regs6, "regs", "setregs") 45111.1Skamil#endif 45121.1Skamil#if defined(HAVE_FPREGS) 45131.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs") 45141.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs") 45151.1Skamil#endif 45161.1Skamil 45171.72Skamil/// ---------------------------------------------------------------------------- 45181.1Skamil 45191.1Skamil#if defined(PT_STEP) 45201.1Skamilstatic void 45211.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored) 45221.1Skamil{ 45231.1Skamil const int exitval = 5; 45241.1Skamil const int sigval = SIGSTOP; 45251.1Skamil pid_t child, wpid; 45261.1Skamil#if defined(TWAIT_HAVE_STATUS) 45271.1Skamil int status; 45281.1Skamil#endif 45291.1Skamil int happy; 45301.95Skamil struct sigaction sa; 45311.81Skamil struct ptrace_siginfo info; 45321.95Skamil sigset_t intmask; 45331.95Skamil struct kinfo_proc2 kp; 45341.95Skamil size_t len = sizeof(kp); 45351.95Skamil 45361.95Skamil int name[6]; 45371.95Skamil const size_t namelen = __arraycount(name); 45381.95Skamil ki_sigset_t kp_sigmask; 45391.95Skamil ki_sigset_t kp_sigignore; 45401.1Skamil 45411.1Skamil#if defined(__arm__) 45421.1Skamil /* PT_STEP not supported on arm 32-bit */ 45431.1Skamil atf_tc_expect_fail("PR kern/52119"); 45441.1Skamil#endif 45451.1Skamil 45461.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 45471.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 45481.1Skamil if (child == 0) { 45491.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 45501.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 45511.1Skamil 45521.95Skamil if (masked) { 45531.95Skamil sigemptyset(&intmask); 45541.95Skamil sigaddset(&intmask, SIGTRAP); 45551.95Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 45561.95Skamil } 45571.95Skamil 45581.95Skamil if (ignored) { 45591.95Skamil memset(&sa, 0, sizeof(sa)); 45601.95Skamil sa.sa_handler = SIG_IGN; 45611.95Skamil sigemptyset(&sa.sa_mask); 45621.95Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 45631.95Skamil } 45641.95Skamil 45651.1Skamil happy = check_happy(999); 45661.1Skamil 45671.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 45681.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 45691.1Skamil 45701.1Skamil FORKEE_ASSERT_EQ(happy, check_happy(999)); 45711.1Skamil 45721.13Schristos DPRINTF("Before exiting of the child process\n"); 45731.1Skamil _exit(exitval); 45741.1Skamil } 45751.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 45761.1Skamil 45771.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45781.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 45791.1Skamil 45801.1Skamil validate_status_stopped(status, sigval); 45811.1Skamil 45821.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 45831.81Skamil SYSCALL_REQUIRE( 45841.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 45851.81Skamil 45861.81Skamil DPRINTF("Before checking siginfo_t\n"); 45871.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 45881.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 45891.81Skamil 45901.95Skamil name[0] = CTL_KERN, 45911.95Skamil name[1] = KERN_PROC2, 45921.95Skamil name[2] = KERN_PROC_PID; 45931.95Skamil name[3] = child; 45941.95Skamil name[4] = sizeof(kp); 45951.95Skamil name[5] = 1; 45961.95Skamil 45971.95Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 45981.95Skamil 45991.95Skamil if (masked) 46001.95Skamil kp_sigmask = kp.p_sigmask; 46011.95Skamil 46021.95Skamil if (ignored) 46031.95Skamil kp_sigignore = kp.p_sigignore; 46041.95Skamil 46051.1Skamil while (N --> 0) { 46061.2Skamil if (setstep) { 46071.13Schristos DPRINTF("Before resuming the child process where it " 46081.2Skamil "left off and without signal to be sent (use " 46091.9Skamil "PT_SETSTEP and PT_CONTINUE)\n"); 46101.13Schristos SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1); 46111.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) 46121.2Skamil != -1); 46131.2Skamil } else { 46141.13Schristos DPRINTF("Before resuming the child process where it " 46151.2Skamil "left off and without signal to be sent (use " 46161.2Skamil "PT_STEP)\n"); 46171.13Schristos SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) 46181.2Skamil != -1); 46191.2Skamil } 46201.1Skamil 46211.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46221.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 46231.1Skamil child); 46241.1Skamil 46251.1Skamil validate_status_stopped(status, SIGTRAP); 46261.2Skamil 46271.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 46281.81Skamil SYSCALL_REQUIRE( 46291.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 46301.81Skamil 46311.81Skamil DPRINTF("Before checking siginfo_t\n"); 46321.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 46331.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE); 46341.81Skamil 46351.2Skamil if (setstep) { 46361.13Schristos SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1); 46371.2Skamil } 46381.95Skamil 46391.95Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 46401.95Skamil 46411.95Skamil if (masked) { 46421.95Skamil DPRINTF("kp_sigmask=" 46431.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46441.95Skamil PRIx32 "\n", 46451.95Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 46461.95Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 46471.95Skamil 46481.95Skamil DPRINTF("kp.p_sigmask=" 46491.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46501.95Skamil PRIx32 "\n", 46511.95Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 46521.95Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 46531.95Skamil 46541.95Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 46551.95Skamil sizeof(kp_sigmask))); 46561.95Skamil } 46571.95Skamil 46581.95Skamil if (ignored) { 46591.95Skamil DPRINTF("kp_sigignore=" 46601.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46611.95Skamil PRIx32 "\n", 46621.95Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 46631.95Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 46641.95Skamil 46651.95Skamil DPRINTF("kp.p_sigignore=" 46661.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46671.95Skamil PRIx32 "\n", 46681.95Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 46691.95Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 46701.95Skamil 46711.95Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 46721.95Skamil sizeof(kp_sigignore))); 46731.95Skamil } 46741.1Skamil } 46751.1Skamil 46761.13Schristos DPRINTF("Before resuming the child process where it left off and " 46771.1Skamil "without signal to be sent\n"); 46781.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 46791.1Skamil 46801.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46811.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 46821.1Skamil 46831.1Skamil validate_status_exited(status, exitval); 46841.1Skamil 46851.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46861.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 46871.1Skamil} 46881.1Skamil 46891.73Skamil#define PTRACE_STEP(test, N, setstep) \ 46901.73SkamilATF_TC(test); \ 46911.73SkamilATF_TC_HEAD(test, tc) \ 46921.73Skamil{ \ 46931.73Skamil atf_tc_set_md_var(tc, "descr", \ 46941.74Skamil "Verify " #N " (PT_SETSTEP set to: " #setstep ")"); \ 46951.73Skamil} \ 46961.73Skamil \ 46971.73SkamilATF_TC_BODY(test, tc) \ 46981.73Skamil{ \ 46991.73Skamil \ 47001.95Skamil ptrace_step(N, setstep, false, false); \ 47011.1Skamil} 47021.1Skamil 47031.73SkamilPTRACE_STEP(step1, 1, 0) 47041.73SkamilPTRACE_STEP(step2, 2, 0) 47051.73SkamilPTRACE_STEP(step3, 3, 0) 47061.73SkamilPTRACE_STEP(step4, 4, 0) 47071.73SkamilPTRACE_STEP(setstep1, 1, 1) 47081.73SkamilPTRACE_STEP(setstep2, 2, 1) 47091.73SkamilPTRACE_STEP(setstep3, 3, 1) 47101.73SkamilPTRACE_STEP(setstep4, 4, 1) 47111.95Skamil 47121.95SkamilATF_TC(step_signalmasked); 47131.95SkamilATF_TC_HEAD(step_signalmasked, tc) 47141.95Skamil{ 47151.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP"); 47161.95Skamil} 47171.95Skamil 47181.95SkamilATF_TC_BODY(step_signalmasked, tc) 47191.95Skamil{ 47201.95Skamil 47211.95Skamil ptrace_step(1, 0, true, false); 47221.95Skamil} 47231.95Skamil 47241.95SkamilATF_TC(step_signalignored); 47251.95SkamilATF_TC_HEAD(step_signalignored, tc) 47261.95Skamil{ 47271.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP"); 47281.95Skamil} 47291.95Skamil 47301.95SkamilATF_TC_BODY(step_signalignored, tc) 47311.95Skamil{ 47321.95Skamil 47331.95Skamil ptrace_step(1, 0, false, true); 47341.95Skamil} 47351.1Skamil#endif 47361.1Skamil 47371.73Skamil/// ---------------------------------------------------------------------------- 47381.1Skamil 47391.75Skamilstatic void 47401.75Skamilptrace_kill(const char *type) 47411.1Skamil{ 47421.75Skamil const int sigval = SIGSTOP; 47431.1Skamil pid_t child, wpid; 47441.1Skamil#if defined(TWAIT_HAVE_STATUS) 47451.1Skamil int status; 47461.1Skamil#endif 47471.1Skamil 47481.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 47491.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 47501.1Skamil if (child == 0) { 47511.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 47521.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 47531.1Skamil 47541.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 47551.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 47561.1Skamil 47571.1Skamil /* NOTREACHED */ 47581.1Skamil FORKEE_ASSERTX(0 && 47591.1Skamil "Child should be terminated by a signal from its parent"); 47601.1Skamil } 47611.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 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.1Skamil validate_status_stopped(status, sigval); 47671.1Skamil 47681.75Skamil DPRINTF("Before killing the child process with %s\n", type); 47691.75Skamil if (strcmp(type, "ptrace(PT_KILL)") == 0) { 47701.75Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1); 47711.75Skamil } else if (strcmp(type, "kill(SIGKILL)") == 0) { 47721.75Skamil kill(child, SIGKILL); 47731.75Skamil } else if (strcmp(type, "killpg(SIGKILL)") == 0) { 47741.75Skamil setpgid(child, 0); 47751.75Skamil killpg(getpgid(child), SIGKILL); 47761.75Skamil } 47771.1Skamil 47781.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47791.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47801.1Skamil 47811.75Skamil validate_status_signaled(status, SIGKILL, 0); 47821.1Skamil 47831.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47841.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 47851.1Skamil} 47861.1Skamil 47871.75Skamil#define PTRACE_KILL(test, type) \ 47881.75SkamilATF_TC(test); \ 47891.75SkamilATF_TC_HEAD(test, tc) \ 47901.75Skamil{ \ 47911.75Skamil atf_tc_set_md_var(tc, "descr", \ 47921.75Skamil "Verify killing the child with " type); \ 47931.75Skamil} \ 47941.75Skamil \ 47951.75SkamilATF_TC_BODY(test, tc) \ 47961.75Skamil{ \ 47971.75Skamil \ 47981.75Skamil ptrace_kill(type); \ 47991.1Skamil} 48001.1Skamil 48011.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1 48021.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)") 48031.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)") 48041.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)") 48051.1Skamil 48061.75Skamil/// ---------------------------------------------------------------------------- 48071.1Skamil 48081.77Skamilstatic void 48091.77Skamiltraceme_lwpinfo(const int threads) 48101.1Skamil{ 48111.1Skamil const int sigval = SIGSTOP; 48121.77Skamil const int sigval2 = SIGINT; 48131.1Skamil pid_t child, wpid; 48141.1Skamil#if defined(TWAIT_HAVE_STATUS) 48151.1Skamil int status; 48161.1Skamil#endif 48171.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 48181.77Skamil struct ptrace_siginfo info; 48191.77Skamil 48201.77Skamil /* Maximum number of supported threads in this test */ 48211.77Skamil pthread_t t[3]; 48221.77Skamil int n, rv; 48231.77Skamil 48241.77Skamil ATF_REQUIRE((int)__arraycount(t) >= threads); 48251.1Skamil 48261.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 48271.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 48281.1Skamil if (child == 0) { 48291.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 48301.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 48311.1Skamil 48321.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 48331.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 48341.1Skamil 48351.77Skamil for (n = 0; n < threads; n++) { 48361.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 48371.77Skamil FORKEE_ASSERT(rv == 0); 48381.77Skamil } 48391.77Skamil 48401.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval2)); 48411.77Skamil FORKEE_ASSERT(raise(sigval2) == 0); 48421.77Skamil 48431.77Skamil /* NOTREACHED */ 48441.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 48451.1Skamil } 48461.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 48471.1Skamil 48481.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48491.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48501.1Skamil 48511.1Skamil validate_status_stopped(status, sigval); 48521.1Skamil 48531.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 48541.77Skamil SYSCALL_REQUIRE( 48551.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 48561.77Skamil 48571.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 48581.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 48591.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 48601.77Skamil info.psi_siginfo.si_errno); 48611.77Skamil 48621.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 48631.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 48641.77Skamil 48651.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48661.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48671.1Skamil 48681.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 48691.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 48701.1Skamil 48711.13Schristos DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n", 48721.77Skamil lwp.pl_lwpid); 48731.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 48741.1Skamil 48751.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48761.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48771.1Skamil 48781.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 48791.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 48801.1Skamil 48811.13Schristos DPRINTF("Before resuming the child process where it left off and " 48821.1Skamil "without signal to be sent\n"); 48831.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 48841.1Skamil 48851.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48861.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48871.1Skamil 48881.77Skamil validate_status_stopped(status, sigval2); 48891.77Skamil 48901.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 48911.77Skamil SYSCALL_REQUIRE( 48921.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 48931.77Skamil 48941.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 48951.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 48961.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 48971.77Skamil info.psi_siginfo.si_errno); 48981.77Skamil 48991.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2); 49001.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 49011.77Skamil 49021.77Skamil memset(&lwp, 0, sizeof(lwp)); 49031.77Skamil 49041.77Skamil for (n = 0; n <= threads; n++) { 49051.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 49061.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 49071.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 49081.77Skamil 49091.77Skamil DPRINTF("Assert that the thread exists\n"); 49101.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 49111.77Skamil 49121.77Skamil DPRINTF("Assert that lwp thread %d received expected event\n", 49131.77Skamil lwp.pl_lwpid); 49141.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ? 49151.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 49161.77Skamil } 49171.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 49181.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 49191.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 49201.77Skamil 49211.77Skamil DPRINTF("Assert that there are no more threads\n"); 49221.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 49231.77Skamil 49241.77Skamil DPRINTF("Before resuming the child process where it left off and " 49251.77Skamil "without signal to be sent\n"); 49261.77Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1); 49271.77Skamil 49281.77Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49291.77Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 49301.77Skamil 49311.77Skamil validate_status_signaled(status, SIGKILL, 0); 49321.1Skamil 49331.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49341.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 49351.1Skamil} 49361.1Skamil 49371.77Skamil#define TRACEME_LWPINFO(test, threads) \ 49381.77SkamilATF_TC(test); \ 49391.77SkamilATF_TC_HEAD(test, tc) \ 49401.77Skamil{ \ 49411.77Skamil atf_tc_set_md_var(tc, "descr", \ 49421.77Skamil "Verify LWPINFO with the child with " #threads \ 49431.77Skamil " spawned extra threads"); \ 49441.77Skamil} \ 49451.77Skamil \ 49461.77SkamilATF_TC_BODY(test, tc) \ 49471.77Skamil{ \ 49481.77Skamil \ 49491.77Skamil traceme_lwpinfo(threads); \ 49501.1Skamil} 49511.1Skamil 49521.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0) 49531.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1) 49541.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2) 49551.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3) 49561.77Skamil 49571.77Skamil/// ---------------------------------------------------------------------------- 49581.77Skamil 49591.77Skamil#if defined(TWAIT_HAVE_PID) 49601.77Skamilstatic void 49611.77Skamilattach_lwpinfo(const int threads) 49621.1Skamil{ 49631.77Skamil const int sigval = SIGINT; 49641.1Skamil struct msg_fds parent_tracee, parent_tracer; 49651.1Skamil const int exitval_tracer = 10; 49661.1Skamil pid_t tracee, tracer, wpid; 49671.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 49681.1Skamil#if defined(TWAIT_HAVE_STATUS) 49691.1Skamil int status; 49701.1Skamil#endif 49711.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 49721.77Skamil struct ptrace_siginfo info; 49731.77Skamil 49741.77Skamil /* Maximum number of supported threads in this test */ 49751.77Skamil pthread_t t[3]; 49761.77Skamil int n, rv; 49771.1Skamil 49781.13Schristos DPRINTF("Spawn tracee\n"); 49791.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 49801.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 49811.1Skamil tracee = atf_utils_fork(); 49821.1Skamil if (tracee == 0) { 49831.1Skamil /* Wait for message from the parent */ 49841.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 49851.1Skamil 49861.77Skamil CHILD_FROM_PARENT("spawn threads", parent_tracee, msg); 49871.77Skamil 49881.77Skamil for (n = 0; n < threads; n++) { 49891.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 49901.77Skamil FORKEE_ASSERT(rv == 0); 49911.77Skamil } 49921.77Skamil 49931.77Skamil CHILD_TO_PARENT("tracee exit", parent_tracee, msg); 49941.77Skamil 49951.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 49961.77Skamil FORKEE_ASSERT(raise(sigval) == 0); 49971.77Skamil 49981.77Skamil /* NOTREACHED */ 49991.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 50001.1Skamil } 50011.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 50021.1Skamil 50031.13Schristos DPRINTF("Spawn debugger\n"); 50041.1Skamil tracer = atf_utils_fork(); 50051.1Skamil if (tracer == 0) { 50061.1Skamil /* No IPC to communicate with the child */ 50071.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 50081.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 50091.1Skamil 50101.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 50111.1Skamil FORKEE_REQUIRE_SUCCESS( 50121.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 50131.1Skamil 50141.1Skamil forkee_status_stopped(status, SIGSTOP); 50151.1Skamil 50161.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 50171.77Skamil "tracee"); 50181.77Skamil FORKEE_ASSERT( 50191.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 50201.77Skamil 50211.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 50221.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 50231.77Skamil "si_errno=%#x\n", 50241.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 50251.77Skamil info.psi_siginfo.si_errno); 50261.77Skamil 50271.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 50281.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 50291.77Skamil 50301.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 50311.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 50321.1Skamil != -1); 50331.1Skamil 50341.13Schristos DPRINTF("Assert that there exists a thread\n"); 50351.77Skamil FORKEE_ASSERTX(lwp.pl_lwpid > 0); 50361.1Skamil 50371.13Schristos DPRINTF("Assert that lwp thread %d received event " 50381.77Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 50391.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 50401.1Skamil 50411.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50421.77Skamil "tracee\n"); 50431.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 50441.1Skamil != -1); 50451.1Skamil 50461.77Skamil DPRINTF("Assert that there are no more lwp threads in " 50471.77Skamil "tracee\n"); 50481.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 50491.1Skamil 50501.1Skamil /* Resume tracee with PT_CONTINUE */ 50511.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 50521.1Skamil 50531.1Skamil /* Inform parent that tracer has attached to tracee */ 50541.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 50551.77Skamil 50561.1Skamil /* Wait for parent */ 50571.1Skamil CHILD_FROM_PARENT("tracer wait", parent_tracer, msg); 50581.1Skamil 50591.77Skamil /* Wait for tracee and assert that it raised a signal */ 50601.77Skamil FORKEE_REQUIRE_SUCCESS( 50611.77Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 50621.77Skamil 50631.77Skamil forkee_status_stopped(status, SIGINT); 50641.77Skamil 50651.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 50661.77Skamil "child"); 50671.77Skamil FORKEE_ASSERT( 50681.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 50691.77Skamil 50701.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 50711.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 50721.77Skamil "si_errno=%#x\n", 50731.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 50741.77Skamil info.psi_siginfo.si_errno); 50751.77Skamil 50761.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 50771.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 50781.77Skamil 50791.77Skamil memset(&lwp, 0, sizeof(lwp)); 50801.77Skamil 50811.77Skamil for (n = 0; n <= threads; n++) { 50821.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50831.77Skamil "child\n"); 50841.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, 50851.77Skamil sizeof(lwp)) != -1); 50861.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 50871.77Skamil 50881.77Skamil DPRINTF("Assert that the thread exists\n"); 50891.77Skamil FORKEE_ASSERT(lwp.pl_lwpid > 0); 50901.77Skamil 50911.77Skamil DPRINTF("Assert that lwp thread %d received expected " 50921.77Skamil "event\n", lwp.pl_lwpid); 50931.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 50941.77Skamil info.psi_lwpid == lwp.pl_lwpid ? 50951.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 50961.77Skamil } 50971.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50981.77Skamil "tracee\n"); 50991.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 51001.77Skamil != -1); 51011.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 51021.77Skamil 51031.77Skamil DPRINTF("Assert that there are no more threads\n"); 51041.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 51051.77Skamil 51061.77Skamil DPRINTF("Before resuming the child process where it left off " 51071.77Skamil "and without signal to be sent\n"); 51081.77Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL) 51091.77Skamil != -1); 51101.77Skamil 51111.1Skamil /* Wait for tracee and assert that it exited */ 51121.1Skamil FORKEE_REQUIRE_SUCCESS( 51131.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 51141.1Skamil 51151.77Skamil forkee_status_signaled(status, SIGKILL, 0); 51161.1Skamil 51171.13Schristos DPRINTF("Before exiting of the tracer process\n"); 51181.1Skamil _exit(exitval_tracer); 51191.1Skamil } 51201.1Skamil 51211.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 51221.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 51231.1Skamil 51241.77Skamil DPRINTF("Resume the tracee and spawn threads\n"); 51251.77Skamil PARENT_TO_CHILD("spawn threads", parent_tracee, msg); 51261.77Skamil 51271.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 51281.77Skamil PARENT_FROM_CHILD("tracee exit", parent_tracee, msg); 51291.1Skamil 51301.77Skamil DPRINTF("Resume the tracer and let it detect multiple threads\n"); 51311.1Skamil PARENT_TO_CHILD("tracer wait", parent_tracer, msg); 51321.1Skamil 51331.13Schristos DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n", 51341.1Skamil TWAIT_FNAME); 51351.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 51361.1Skamil tracer); 51371.1Skamil 51381.1Skamil validate_status_exited(status, exitval_tracer); 51391.1Skamil 51401.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 51411.1Skamil TWAIT_FNAME); 51421.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 51431.1Skamil tracee); 51441.1Skamil 51451.77Skamil validate_status_signaled(status, SIGKILL, 0); 51461.1Skamil 51471.1Skamil msg_close(&parent_tracer); 51481.1Skamil msg_close(&parent_tracee); 51491.1Skamil} 51501.77Skamil 51511.77Skamil#define ATTACH_LWPINFO(test, threads) \ 51521.77SkamilATF_TC(test); \ 51531.77SkamilATF_TC_HEAD(test, tc) \ 51541.77Skamil{ \ 51551.77Skamil atf_tc_set_md_var(tc, "descr", \ 51561.77Skamil "Verify LWPINFO with the child with " #threads \ 51571.77Skamil " spawned extra threads (tracer is not the original " \ 51581.77Skamil "parent)"); \ 51591.77Skamil} \ 51601.77Skamil \ 51611.77SkamilATF_TC_BODY(test, tc) \ 51621.77Skamil{ \ 51631.77Skamil \ 51641.77Skamil attach_lwpinfo(threads); \ 51651.77Skamil} 51661.77Skamil 51671.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0) 51681.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1) 51691.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2) 51701.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3) 51711.1Skamil#endif 51721.1Skamil 51731.77Skamil/// ---------------------------------------------------------------------------- 51741.77Skamil 51751.1Skamilstatic void 51761.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught) 51771.1Skamil{ 51781.1Skamil const int exitval = 5; 51791.1Skamil const int sigval = SIGINT; 51801.1Skamil const int sigfaked = SIGTRAP; 51811.1Skamil const int sicodefaked = TRAP_BRKPT; 51821.1Skamil pid_t child, wpid; 51831.1Skamil struct sigaction sa; 51841.1Skamil#if defined(TWAIT_HAVE_STATUS) 51851.1Skamil int status; 51861.1Skamil#endif 51871.1Skamil struct ptrace_siginfo info; 51881.1Skamil memset(&info, 0, sizeof(info)); 51891.1Skamil 51901.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 51911.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 51921.1Skamil if (child == 0) { 51931.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 51941.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 51951.1Skamil 51961.79Skamil sa.sa_sigaction = sah; 51971.1Skamil sa.sa_flags = SA_SIGINFO; 51981.1Skamil sigemptyset(&sa.sa_mask); 51991.1Skamil 52001.79Skamil FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL) 52011.79Skamil != -1); 52021.1Skamil 52031.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 52041.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 52051.1Skamil 52061.79Skamil FORKEE_ASSERT_EQ(*signal_caught, 1); 52071.1Skamil 52081.13Schristos DPRINTF("Before exiting of the child process\n"); 52091.1Skamil _exit(exitval); 52101.1Skamil } 52111.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 52121.1Skamil 52131.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52141.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52151.1Skamil 52161.1Skamil validate_status_stopped(status, sigval); 52171.1Skamil 52181.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 52191.61Skre SYSCALL_REQUIRE( 52201.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 52211.1Skamil 52221.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 52231.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 52241.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 52251.1Skamil info.psi_siginfo.si_errno); 52261.1Skamil 52271.79Skamil if (faked) { 52281.79Skamil DPRINTF("Before setting new faked signal to signo=%d " 52291.79Skamil "si_code=%d\n", sigfaked, sicodefaked); 52301.79Skamil info.psi_siginfo.si_signo = sigfaked; 52311.79Skamil info.psi_siginfo.si_code = sicodefaked; 52321.79Skamil } 52331.1Skamil 52341.13Schristos DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n"); 52351.61Skre SYSCALL_REQUIRE( 52361.61Skre ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1); 52371.1Skamil 52381.79Skamil if (faked) { 52391.79Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 52401.79Skamil "child\n"); 52411.79Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 52421.79Skamil sizeof(info)) != -1); 52431.1Skamil 52441.79Skamil DPRINTF("Before checking siginfo_t\n"); 52451.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked); 52461.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked); 52471.79Skamil } 52481.1Skamil 52491.13Schristos DPRINTF("Before resuming the child process where it left off and " 52501.1Skamil "without signal to be sent\n"); 52511.79Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 52521.79Skamil faked ? sigfaked : sigval) != -1); 52531.1Skamil 52541.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52551.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52561.1Skamil 52571.1Skamil validate_status_exited(status, exitval); 52581.1Skamil 52591.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52601.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 52611.1Skamil} 52621.1Skamil 52631.79Skamil#define PTRACE_SIGINFO(test, faked) \ 52641.79SkamilATF_TC(test); \ 52651.79SkamilATF_TC_HEAD(test, tc) \ 52661.79Skamil{ \ 52671.79Skamil atf_tc_set_md_var(tc, "descr", \ 52681.79Skamil "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls" \ 52691.79Skamil "with%s setting signal to new value", faked ? "" : "out"); \ 52701.79Skamil} \ 52711.79Skamil \ 52721.79Skamilstatic int test##_caught = 0; \ 52731.79Skamil \ 52741.79Skamilstatic void \ 52751.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx) \ 52761.79Skamil{ \ 52771.79Skamil if (faked) { \ 52781.79Skamil FORKEE_ASSERT_EQ(sig, SIGTRAP); \ 52791.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP); \ 52801.79Skamil FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT); \ 52811.79Skamil } else { \ 52821.79Skamil FORKEE_ASSERT_EQ(sig, SIGINT); \ 52831.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGINT); \ 52841.79Skamil FORKEE_ASSERT_EQ(info->si_code, SI_LWP); \ 52851.79Skamil } \ 52861.79Skamil \ 52871.79Skamil ++ test##_caught; \ 52881.79Skamil} \ 52891.79Skamil \ 52901.79SkamilATF_TC_BODY(test, tc) \ 52911.79Skamil{ \ 52921.79Skamil \ 52931.79Skamil ptrace_siginfo(faked, test##_sighandler, & test##_caught); \ 52941.79Skamil} 52951.79Skamil 52961.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false) 52971.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true) 52981.79Skamil 52991.79Skamil/// ---------------------------------------------------------------------------- 53001.79Skamil 53011.97Skamilstatic void 53021.97Skamiltraceme_exec(bool masked, bool ignored) 53031.1Skamil{ 53041.1Skamil const int sigval = SIGTRAP; 53051.1Skamil pid_t child, wpid; 53061.1Skamil#if defined(TWAIT_HAVE_STATUS) 53071.1Skamil int status; 53081.1Skamil#endif 53091.97Skamil struct sigaction sa; 53101.97Skamil struct ptrace_siginfo info; 53111.97Skamil sigset_t intmask; 53121.97Skamil struct kinfo_proc2 kp; 53131.97Skamil size_t len = sizeof(kp); 53141.97Skamil 53151.97Skamil int name[6]; 53161.97Skamil const size_t namelen = __arraycount(name); 53171.97Skamil ki_sigset_t kp_sigmask; 53181.97Skamil ki_sigset_t kp_sigignore; 53191.1Skamil 53201.1Skamil memset(&info, 0, sizeof(info)); 53211.1Skamil 53221.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 53231.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 53241.1Skamil if (child == 0) { 53251.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 53261.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 53271.1Skamil 53281.97Skamil if (masked) { 53291.97Skamil sigemptyset(&intmask); 53301.97Skamil sigaddset(&intmask, sigval); 53311.97Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 53321.97Skamil } 53331.97Skamil 53341.97Skamil if (ignored) { 53351.97Skamil memset(&sa, 0, sizeof(sa)); 53361.97Skamil sa.sa_handler = SIG_IGN; 53371.97Skamil sigemptyset(&sa.sa_mask); 53381.97Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 53391.97Skamil } 53401.97Skamil 53411.13Schristos DPRINTF("Before calling execve(2) from child\n"); 53421.1Skamil execlp("/bin/echo", "/bin/echo", NULL); 53431.1Skamil 53441.1Skamil FORKEE_ASSERT(0 && "Not reached"); 53451.1Skamil } 53461.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 53471.1Skamil 53481.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53491.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 53501.1Skamil 53511.1Skamil validate_status_stopped(status, sigval); 53521.1Skamil 53531.97Skamil name[0] = CTL_KERN, 53541.97Skamil name[1] = KERN_PROC2, 53551.97Skamil name[2] = KERN_PROC_PID; 53561.97Skamil name[3] = getpid(); 53571.97Skamil name[4] = sizeof(kp); 53581.97Skamil name[5] = 1; 53591.97Skamil 53601.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 53611.97Skamil 53621.97Skamil if (masked) 53631.97Skamil kp_sigmask = kp.p_sigmask; 53641.97Skamil 53651.97Skamil if (ignored) 53661.97Skamil kp_sigignore = kp.p_sigignore; 53671.97Skamil 53681.97Skamil name[3] = getpid(); 53691.97Skamil 53701.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 53711.97Skamil 53721.97Skamil if (masked) { 53731.97Skamil DPRINTF("kp_sigmask=" 53741.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53751.97Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 53761.97Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 53771.97Skamil 53781.97Skamil DPRINTF("kp.p_sigmask=" 53791.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53801.97Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 53811.97Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 53821.97Skamil 53831.97Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 53841.97Skamil sizeof(kp_sigmask))); 53851.97Skamil } 53861.97Skamil 53871.97Skamil if (ignored) { 53881.97Skamil DPRINTF("kp_sigignore=" 53891.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53901.97Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 53911.97Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 53921.97Skamil 53931.97Skamil DPRINTF("kp.p_sigignore=" 53941.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53951.97Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 53961.97Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 53971.97Skamil 53981.97Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 53991.97Skamil sizeof(kp_sigignore))); 54001.97Skamil } 54011.97Skamil 54021.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 54031.61Skre SYSCALL_REQUIRE( 54041.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 54051.1Skamil 54061.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 54071.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 54081.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 54091.1Skamil info.psi_siginfo.si_errno); 54101.1Skamil 54111.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 54121.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 54131.1Skamil 54141.13Schristos DPRINTF("Before resuming the child process where it left off and " 54151.1Skamil "without signal to be sent\n"); 54161.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 54171.1Skamil 54181.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54191.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 54201.1Skamil 54211.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54221.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 54231.1Skamil} 54241.1Skamil 54251.97Skamil#define TRACEME_EXEC(test, masked, ignored) \ 54261.97SkamilATF_TC(test); \ 54271.97SkamilATF_TC_HEAD(test, tc) \ 54281.97Skamil{ \ 54291.97Skamil atf_tc_set_md_var(tc, "descr", \ 54301.97Skamil "Detect SIGTRAP TRAP_EXEC from " \ 54311.97Skamil "child%s%s", masked ? " with masked signal" : "", \ 54321.97Skamil masked ? " with ignored signal" : ""); \ 54331.97Skamil} \ 54341.97Skamil \ 54351.97SkamilATF_TC_BODY(test, tc) \ 54361.97Skamil{ \ 54371.97Skamil \ 54381.97Skamil traceme_exec(masked, ignored); \ 54391.97Skamil} 54401.97Skamil 54411.97SkamilTRACEME_EXEC(traceme_exec, false, false) 54421.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false) 54431.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true) 54441.97Skamil 54451.82Skamil/// ---------------------------------------------------------------------------- 54461.82Skamil 54471.83Skamilstatic volatile int done; 54481.1Skamil 54491.83Skamilstatic void * 54501.83Skamiltrace_threads_cb(void *arg __unused) 54511.1Skamil{ 54521.1Skamil 54531.83Skamil done++; 54541.83Skamil 54551.83Skamil while (done < 3) 54561.83Skamil continue; 54571.83Skamil 54581.83Skamil return NULL; 54591.1Skamil} 54601.1Skamil 54611.83Skamilstatic void 54621.83Skamiltrace_threads(bool trace_create, bool trace_exit) 54631.1Skamil{ 54641.1Skamil const int sigval = SIGSTOP; 54651.1Skamil pid_t child, wpid; 54661.1Skamil#if defined(TWAIT_HAVE_STATUS) 54671.1Skamil int status; 54681.1Skamil#endif 54691.1Skamil ptrace_state_t state; 54701.1Skamil const int slen = sizeof(state); 54711.1Skamil ptrace_event_t event; 54721.1Skamil const int elen = sizeof(event); 54731.83Skamil struct ptrace_siginfo info; 54741.83Skamil 54751.83Skamil pthread_t t[3]; 54761.83Skamil int rv; 54771.83Skamil size_t n; 54781.1Skamil lwpid_t lid; 54791.83Skamil 54801.83Skamil /* Track created and exited threads */ 54811.83Skamil bool traced_lwps[__arraycount(t)]; 54821.83Skamil 54831.128Skamil#if !TEST_LWP_ENABLED 54841.120Skamil if (trace_create || trace_exit) 54851.119Skamil atf_tc_skip("PR kern/51995"); 54861.128Skamil#endif 54871.1Skamil 54881.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 54891.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 54901.1Skamil if (child == 0) { 54911.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 54921.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 54931.1Skamil 54941.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 54951.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 54961.1Skamil 54971.83Skamil for (n = 0; n < __arraycount(t); n++) { 54981.83Skamil rv = pthread_create(&t[n], NULL, trace_threads_cb, 54991.83Skamil NULL); 55001.83Skamil FORKEE_ASSERT(rv == 0); 55011.83Skamil } 55021.1Skamil 55031.83Skamil for (n = 0; n < __arraycount(t); n++) { 55041.83Skamil rv = pthread_join(t[n], NULL); 55051.83Skamil FORKEE_ASSERT(rv == 0); 55061.83Skamil } 55071.1Skamil 55081.83Skamil /* 55091.83Skamil * There is race between _exit() and pthread_join() detaching 55101.83Skamil * a thread. For simplicity kill the process after detecting 55111.83Skamil * LWP events. 55121.83Skamil */ 55131.83Skamil while (true) 55141.83Skamil continue; 55151.1Skamil 55161.83Skamil FORKEE_ASSERT(0 && "Not reached"); 55171.1Skamil } 55181.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 55191.1Skamil 55201.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 55211.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 55221.1Skamil 55231.1Skamil validate_status_stopped(status, sigval); 55241.1Skamil 55251.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 55261.83Skamil SYSCALL_REQUIRE( 55271.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55281.1Skamil 55291.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55301.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 55311.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55321.83Skamil info.psi_siginfo.si_errno); 55331.1Skamil 55341.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 55351.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 55361.1Skamil 55371.83Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 55381.83Skamil memset(&event, 0, sizeof(event)); 55391.83Skamil if (trace_create) 55401.83Skamil event.pe_set_event |= PTRACE_LWP_CREATE; 55411.83Skamil if (trace_exit) 55421.83Skamil event.pe_set_event |= PTRACE_LWP_EXIT; 55431.83Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 55441.1Skamil 55451.13Schristos DPRINTF("Before resuming the child process where it left off and " 55461.1Skamil "without signal to be sent\n"); 55471.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 55481.1Skamil 55491.83Skamil memset(traced_lwps, 0, sizeof(traced_lwps)); 55501.1Skamil 55511.83Skamil for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) { 55521.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 55531.83Skamil "SIGTRAP\n", TWAIT_FNAME); 55541.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 55551.83Skamil child); 55561.1Skamil 55571.83Skamil validate_status_stopped(status, SIGTRAP); 55581.1Skamil 55591.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 55601.83Skamil "child\n"); 55611.83Skamil SYSCALL_REQUIRE( 55621.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55631.1Skamil 55641.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55651.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 55661.83Skamil "si_errno=%#x\n", 55671.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55681.83Skamil info.psi_siginfo.si_errno); 55691.1Skamil 55701.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 55711.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 55721.1Skamil 55731.83Skamil SYSCALL_REQUIRE( 55741.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 55751.1Skamil 55761.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 55771.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 55781.1Skamil 55791.83Skamil lid = state.pe_lwp; 55801.83Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 55811.1Skamil 55821.83Skamil traced_lwps[lid - 1] = true; 55831.1Skamil 55841.83Skamil DPRINTF("Before resuming the child process where it left off " 55851.83Skamil "and without signal to be sent\n"); 55861.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 55871.83Skamil } 55881.1Skamil 55891.83Skamil for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) { 55901.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 55911.83Skamil "SIGTRAP\n", TWAIT_FNAME); 55921.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 55931.83Skamil child); 55941.1Skamil 55951.83Skamil validate_status_stopped(status, SIGTRAP); 55961.1Skamil 55971.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 55981.83Skamil "child\n"); 55991.83Skamil SYSCALL_REQUIRE( 56001.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 56011.1Skamil 56021.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 56031.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 56041.83Skamil "si_errno=%#x\n", 56051.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 56061.83Skamil info.psi_siginfo.si_errno); 56071.1Skamil 56081.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 56091.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 56101.1Skamil 56111.83Skamil SYSCALL_REQUIRE( 56121.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 56131.1Skamil 56141.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 56151.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 56161.1Skamil 56171.83Skamil lid = state.pe_lwp; 56181.83Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 56191.1Skamil 56201.83Skamil if (trace_create) { 56211.83Skamil ATF_REQUIRE(traced_lwps[lid - 1] == true); 56221.83Skamil traced_lwps[lid - 1] = false; 56231.83Skamil } 56241.1Skamil 56251.83Skamil DPRINTF("Before resuming the child process where it left off " 56261.83Skamil "and without signal to be sent\n"); 56271.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56281.83Skamil } 56291.1Skamil 56301.83Skamil kill(child, SIGKILL); 56311.1Skamil 56321.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 56331.1Skamil TWAIT_FNAME); 56341.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56351.1Skamil 56361.83Skamil validate_status_signaled(status, SIGKILL, 0); 56371.1Skamil 56381.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 56391.1Skamil TWAIT_FNAME); 56401.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 56411.1Skamil} 56421.1Skamil 56431.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit) \ 56441.83SkamilATF_TC(test); \ 56451.83SkamilATF_TC_HEAD(test, tc) \ 56461.83Skamil{ \ 56471.83Skamil atf_tc_set_md_var(tc, "descr", \ 56481.83Skamil "Verify spawning threads with%s tracing LWP create and" \ 56491.83Skamil "with%s tracing LWP exit", trace_create ? "" : "out", \ 56501.83Skamil trace_exit ? "" : "out"); \ 56511.83Skamil} \ 56521.83Skamil \ 56531.83SkamilATF_TC_BODY(test, tc) \ 56541.83Skamil{ \ 56551.83Skamil \ 56561.83Skamil trace_threads(trace_create, trace_exit); \ 56571.83Skamil} 56581.83Skamil 56591.119SkamilTRACE_THREADS(trace_thread_nolwpevents, false, false) 56601.119SkamilTRACE_THREADS(trace_thread_lwpexit, false, true) 56611.119SkamilTRACE_THREADS(trace_thread_lwpcreate, true, false) 56621.119SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true) 56631.83Skamil 56641.83Skamil/// ---------------------------------------------------------------------------- 56651.83Skamil 56661.84SkamilATF_TC(signal_mask_unrelated); 56671.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc) 56681.1Skamil{ 56691.1Skamil atf_tc_set_md_var(tc, "descr", 56701.1Skamil "Verify that masking single unrelated signal does not stop tracer " 56711.1Skamil "from catching other signals"); 56721.1Skamil} 56731.1Skamil 56741.84SkamilATF_TC_BODY(signal_mask_unrelated, tc) 56751.1Skamil{ 56761.1Skamil const int exitval = 5; 56771.1Skamil const int sigval = SIGSTOP; 56781.1Skamil const int sigmasked = SIGTRAP; 56791.1Skamil const int signotmasked = SIGINT; 56801.1Skamil pid_t child, wpid; 56811.1Skamil#if defined(TWAIT_HAVE_STATUS) 56821.1Skamil int status; 56831.1Skamil#endif 56841.1Skamil sigset_t intmask; 56851.1Skamil 56861.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 56871.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 56881.1Skamil if (child == 0) { 56891.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 56901.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 56911.1Skamil 56921.1Skamil sigemptyset(&intmask); 56931.1Skamil sigaddset(&intmask, sigmasked); 56941.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 56951.1Skamil 56961.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 56971.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 56981.1Skamil 56991.13Schristos DPRINTF("Before raising %s from child\n", 57001.1Skamil strsignal(signotmasked)); 57011.1Skamil FORKEE_ASSERT(raise(signotmasked) == 0); 57021.1Skamil 57031.13Schristos DPRINTF("Before exiting of the child process\n"); 57041.1Skamil _exit(exitval); 57051.1Skamil } 57061.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 57071.1Skamil 57081.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57091.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57101.1Skamil 57111.1Skamil validate_status_stopped(status, sigval); 57121.1Skamil 57131.13Schristos DPRINTF("Before resuming the child process where it left off and " 57141.1Skamil "without signal to be sent\n"); 57151.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 57161.1Skamil 57171.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57181.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57191.1Skamil 57201.1Skamil validate_status_stopped(status, signotmasked); 57211.1Skamil 57221.13Schristos DPRINTF("Before resuming the child process where it left off and " 57231.1Skamil "without signal to be sent\n"); 57241.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 57251.1Skamil 57261.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57271.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57281.1Skamil 57291.1Skamil validate_status_exited(status, exitval); 57301.1Skamil 57311.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57321.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 57331.1Skamil} 57341.1Skamil 57351.84Skamil/// ---------------------------------------------------------------------------- 57361.84Skamil 57371.1Skamil#if defined(TWAIT_HAVE_PID) 57381.99Skamilstatic void 57391.126Skamilfork2_body(const char *fn, bool masked, bool ignored) 57401.1Skamil{ 57411.1Skamil const int exitval = 5; 57421.126Skamil const int exitval2 = 0; /* Match exit status from /bin/echo */ 57431.1Skamil const int sigval = SIGSTOP; 57441.99Skamil pid_t child, child2 = 0, wpid; 57451.1Skamil#if defined(TWAIT_HAVE_STATUS) 57461.1Skamil int status; 57471.1Skamil#endif 57481.1Skamil ptrace_state_t state; 57491.1Skamil const int slen = sizeof(state); 57501.1Skamil ptrace_event_t event; 57511.1Skamil const int elen = sizeof(event); 57521.99Skamil struct sigaction sa; 57531.99Skamil struct ptrace_siginfo info; 57541.99Skamil sigset_t intmask; 57551.99Skamil struct kinfo_proc2 kp; 57561.99Skamil size_t len = sizeof(kp); 57571.99Skamil 57581.99Skamil int name[6]; 57591.99Skamil const size_t namelen = __arraycount(name); 57601.99Skamil ki_sigset_t kp_sigmask; 57611.99Skamil ki_sigset_t kp_sigignore; 57621.1Skamil 57631.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 57641.14Schristos 57651.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 57661.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 57671.1Skamil if (child == 0) { 57681.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 57691.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 57701.1Skamil 57711.99Skamil if (masked) { 57721.99Skamil sigemptyset(&intmask); 57731.99Skamil sigaddset(&intmask, SIGTRAP); 57741.99Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 57751.99Skamil } 57761.99Skamil 57771.99Skamil if (ignored) { 57781.99Skamil memset(&sa, 0, sizeof(sa)); 57791.99Skamil sa.sa_handler = SIG_IGN; 57801.99Skamil sigemptyset(&sa.sa_mask); 57811.99Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 57821.99Skamil } 57831.1Skamil 57841.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 57851.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 57861.1Skamil 57871.126Skamil if (strcmp(fn, "spawn") == 0) { 57881.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 57891.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 57901.126Skamil } else { 57911.126Skamil if (strcmp(fn, "fork") == 0) { 57921.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 57931.126Skamil } else { 57941.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 57951.126Skamil } 57961.126Skamil if (child2 == 0) 57971.126Skamil _exit(exitval2); 57981.126Skamil } 57991.1Skamil 58001.1Skamil FORKEE_REQUIRE_SUCCESS 58011.99Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 58021.1Skamil 58031.1Skamil forkee_status_exited(status, exitval2); 58041.1Skamil 58051.13Schristos DPRINTF("Before exiting of the child process\n"); 58061.1Skamil _exit(exitval); 58071.1Skamil } 58081.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 58091.1Skamil 58101.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 58111.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 58121.1Skamil 58131.1Skamil validate_status_stopped(status, sigval); 58141.1Skamil 58151.99Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 58161.99Skamil SYSCALL_REQUIRE( 58171.99Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 58181.99Skamil 58191.99Skamil DPRINTF("Before checking siginfo_t\n"); 58201.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 58211.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 58221.1Skamil 58231.99Skamil name[0] = CTL_KERN, 58241.99Skamil name[1] = KERN_PROC2, 58251.99Skamil name[2] = KERN_PROC_PID; 58261.99Skamil name[3] = child; 58271.99Skamil name[4] = sizeof(kp); 58281.99Skamil name[5] = 1; 58291.1Skamil 58301.99Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 58311.1Skamil 58321.99Skamil if (masked) 58331.99Skamil kp_sigmask = kp.p_sigmask; 58341.1Skamil 58351.99Skamil if (ignored) 58361.99Skamil kp_sigignore = kp.p_sigignore; 58371.1Skamil 58381.126Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 58391.126Skamil strcmp(fn, "spawn") == 0 ? "|PTRACE_POSIX_SPAWN" : "", 58401.126Skamil strcmp(fn, "fork") == 0 ? "|PTRACE_FORK" : "", 58411.126Skamil strcmp(fn, "vfork") == 0 ? "|PTRACE_VFORK" : "", 58421.126Skamil strcmp(fn, "vforkdone") == 0 ? "|PTRACE_VFORK_DONE" : "", child); 58431.99Skamil event.pe_set_event = 0; 58441.126Skamil if (strcmp(fn, "spawn") == 0) 58451.126Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 58461.126Skamil if (strcmp(fn, "fork") == 0) 58471.99Skamil event.pe_set_event |= PTRACE_FORK; 58481.126Skamil if (strcmp(fn, "vfork") == 0) 58491.99Skamil event.pe_set_event |= PTRACE_VFORK; 58501.126Skamil if (strcmp(fn, "vforkdone") == 0) 58511.99Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 58521.99Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 58531.1Skamil 58541.99Skamil DPRINTF("Before resuming the child process where it left off and " 58551.99Skamil "without signal to be sent\n"); 58561.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 58571.1Skamil 58581.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 58591.126Skamil strcmp(fn, "vfork") == 0) { 58601.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 58611.99Skamil child); 58621.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 58631.99Skamil child); 58641.1Skamil 58651.99Skamil validate_status_stopped(status, SIGTRAP); 58661.1Skamil 58671.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 58681.1Skamil 58691.99Skamil if (masked) { 58701.99Skamil DPRINTF("kp_sigmask=" 58711.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58721.99Skamil PRIx32 "\n", 58731.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 58741.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 58751.1Skamil 58761.99Skamil DPRINTF("kp.p_sigmask=" 58771.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58781.99Skamil PRIx32 "\n", 58791.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 58801.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 58811.1Skamil 58821.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 58831.99Skamil sizeof(kp_sigmask))); 58841.99Skamil } 58851.1Skamil 58861.99Skamil if (ignored) { 58871.99Skamil DPRINTF("kp_sigignore=" 58881.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58891.99Skamil PRIx32 "\n", 58901.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 58911.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 58921.1Skamil 58931.99Skamil DPRINTF("kp.p_sigignore=" 58941.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58951.99Skamil PRIx32 "\n", 58961.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 58971.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 58981.1Skamil 58991.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 59001.99Skamil sizeof(kp_sigignore))); 59011.99Skamil } 59021.1Skamil 59031.99Skamil SYSCALL_REQUIRE( 59041.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 59051.126Skamil if (strcmp(fn, "spawn") == 0) { 59061.126Skamil ATF_REQUIRE_EQ( 59071.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 59081.126Skamil PTRACE_POSIX_SPAWN); 59091.126Skamil } 59101.126Skamil if (strcmp(fn, "fork") == 0) { 59111.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 59121.99Skamil PTRACE_FORK); 59131.99Skamil } 59141.126Skamil if (strcmp(fn, "vfork") == 0) { 59151.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 59161.99Skamil PTRACE_VFORK); 59171.99Skamil } 59181.1Skamil 59191.99Skamil child2 = state.pe_other_pid; 59201.99Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 59211.1Skamil 59221.99Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 59231.99Skamil "%d\n", TWAIT_FNAME, child2, child); 59241.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 59251.99Skamil child2); 59261.1Skamil 59271.99Skamil validate_status_stopped(status, SIGTRAP); 59281.1Skamil 59291.99Skamil name[3] = child2; 59301.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 59311.1Skamil 59321.99Skamil if (masked) { 59331.99Skamil DPRINTF("kp_sigmask=" 59341.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59351.99Skamil PRIx32 "\n", 59361.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 59371.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 59381.1Skamil 59391.99Skamil DPRINTF("kp.p_sigmask=" 59401.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59411.99Skamil PRIx32 "\n", 59421.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 59431.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 59441.14Schristos 59451.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 59461.99Skamil sizeof(kp_sigmask))); 59471.99Skamil } 59481.1Skamil 59491.99Skamil if (ignored) { 59501.99Skamil DPRINTF("kp_sigignore=" 59511.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59521.99Skamil PRIx32 "\n", 59531.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 59541.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 59551.1Skamil 59561.99Skamil DPRINTF("kp.p_sigignore=" 59571.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59581.99Skamil PRIx32 "\n", 59591.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 59601.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 59611.1Skamil 59621.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 59631.99Skamil sizeof(kp_sigignore))); 59641.99Skamil } 59651.1Skamil 59661.99Skamil SYSCALL_REQUIRE( 59671.99Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 59681.126Skamil if (strcmp(fn, "spawn") == 0) { 59691.126Skamil ATF_REQUIRE_EQ( 59701.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 59711.126Skamil PTRACE_POSIX_SPAWN); 59721.126Skamil } 59731.126Skamil if (strcmp(fn, "fork") == 0) { 59741.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 59751.99Skamil PTRACE_FORK); 59761.99Skamil } 59771.126Skamil if (strcmp(fn, "vfork") == 0) { 59781.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 59791.99Skamil PTRACE_VFORK); 59801.99Skamil } 59811.1Skamil 59821.99Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 59831.1Skamil 59841.99Skamil DPRINTF("Before resuming the forkee process where it left off " 59851.99Skamil "and without signal to be sent\n"); 59861.99Skamil SYSCALL_REQUIRE( 59871.99Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 59881.1Skamil 59891.99Skamil DPRINTF("Before resuming the child process where it left off " 59901.99Skamil "and without signal to be sent\n"); 59911.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 59921.1Skamil } 59931.1Skamil 59941.126Skamil if (strcmp(fn, "vforkdone") == 0) { 59951.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 59961.99Skamil child); 59971.99Skamil TWAIT_REQUIRE_SUCCESS( 59981.99Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 59991.1Skamil 60001.99Skamil validate_status_stopped(status, SIGTRAP); 60011.1Skamil 60021.99Skamil name[3] = child; 60031.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 60041.1Skamil 60051.102Skamil /* 60061.102Skamil * SIGCHLD is now pending in the signal queue and 60071.102Skamil * the kernel presents it to userland as a masked signal. 60081.102Skamil */ 60091.102Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 60101.102Skamil 60111.99Skamil if (masked) { 60121.99Skamil DPRINTF("kp_sigmask=" 60131.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60141.99Skamil PRIx32 "\n", 60151.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 60161.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 60171.1Skamil 60181.99Skamil DPRINTF("kp.p_sigmask=" 60191.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60201.99Skamil PRIx32 "\n", 60211.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 60221.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 60231.1Skamil 60241.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 60251.99Skamil sizeof(kp_sigmask))); 60261.99Skamil } 60271.1Skamil 60281.99Skamil if (ignored) { 60291.99Skamil DPRINTF("kp_sigignore=" 60301.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60311.99Skamil PRIx32 "\n", 60321.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 60331.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 60341.1Skamil 60351.99Skamil DPRINTF("kp.p_sigignore=" 60361.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60371.99Skamil PRIx32 "\n", 60381.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 60391.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 60401.1Skamil 60411.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 60421.99Skamil sizeof(kp_sigignore))); 60431.99Skamil } 60441.1Skamil 60451.99Skamil SYSCALL_REQUIRE( 60461.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 60471.99Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 60481.1Skamil 60491.99Skamil child2 = state.pe_other_pid; 60501.99Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 60511.99Skamil child2); 60521.1Skamil 60531.99Skamil DPRINTF("Before resuming the child process where it left off " 60541.99Skamil "and without signal to be sent\n"); 60551.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60561.99Skamil } 60571.1Skamil 60581.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 60591.126Skamil strcmp(fn, "vfork") == 0) { 60601.99Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 60611.99Skamil "\n", TWAIT_FNAME); 60621.99Skamil TWAIT_REQUIRE_SUCCESS( 60631.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 60641.1Skamil 60651.99Skamil validate_status_exited(status, exitval2); 60661.1Skamil 60671.99Skamil DPRINTF("Before calling %s() for the forkee - expected no " 60681.99Skamil "process\n", TWAIT_FNAME); 60691.99Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 60701.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 60711.99Skamil } 60721.1Skamil 60731.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 60741.1Skamil "SIGCHLD\n", TWAIT_FNAME); 60751.57Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60761.1Skamil 60771.1Skamil validate_status_stopped(status, SIGCHLD); 60781.1Skamil 60791.57Skamil DPRINTF("Before resuming the child process where it left off and " 60801.1Skamil "without signal to be sent\n"); 60811.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60821.1Skamil 60831.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 60841.1Skamil TWAIT_FNAME); 60851.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60861.1Skamil 60871.1Skamil validate_status_exited(status, exitval); 60881.1Skamil 60891.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 60901.57Skamil TWAIT_FNAME); 60911.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 60921.1Skamil} 60931.1Skamil 60941.126Skamil#define FORK2_TEST(name,fn,masked,ignored) \ 60951.99SkamilATF_TC(name); \ 60961.99SkamilATF_TC_HEAD(name, tc) \ 60971.99Skamil{ \ 60981.126Skamil atf_tc_set_md_var(tc, "descr", "Verify that " fn " is caught " \ 60991.99Skamil "regardless of signal %s%s", \ 61001.99Skamil masked ? "masked" : "", ignored ? "ignored" : ""); \ 61011.99Skamil} \ 61021.99Skamil \ 61031.99SkamilATF_TC_BODY(name, tc) \ 61041.99Skamil{ \ 61051.99Skamil \ 61061.126Skamil fork2_body(fn, masked, ignored); \ 61071.1Skamil} 61081.1Skamil 61091.126SkamilFORK2_TEST(posix_spawn_singalmasked, "spawn", true, false) 61101.126SkamilFORK2_TEST(posix_spawn_singalignored, "spawn", false, true) 61111.126SkamilFORK2_TEST(fork_singalmasked, "fork", true, false) 61121.126SkamilFORK2_TEST(fork_singalignored, "fork", false, true) 61131.110Skamil#if TEST_VFORK_ENABLED 61141.126SkamilFORK2_TEST(vfork_singalmasked, "vfork", true, false) 61151.126SkamilFORK2_TEST(vfork_singalignored, "vfork", false, true) 61161.126SkamilFORK2_TEST(vforkdone_singalmasked, "vforkdone", true, false) 61171.126SkamilFORK2_TEST(vforkdone_singalignored, "vforkdone", false, true) 61181.1Skamil#endif 61191.110Skamil#endif 61201.1Skamil 61211.99Skamil/// ---------------------------------------------------------------------------- 61221.1Skamil 61231.83Skamilvolatile lwpid_t the_lwp_id = 0; 61241.83Skamil 61251.83Skamilstatic void 61261.83Skamillwp_main_func(void *arg) 61271.83Skamil{ 61281.83Skamil the_lwp_id = _lwp_self(); 61291.83Skamil _lwp_exit(); 61301.83Skamil} 61311.83Skamil 61321.1SkamilATF_TC(signal9); 61331.1SkamilATF_TC_HEAD(signal9, tc) 61341.1Skamil{ 61351.1Skamil atf_tc_set_md_var(tc, "descr", 61361.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 61371.1Skamil "catching PTRACE_LWP_CREATE breakpoint"); 61381.1Skamil} 61391.1Skamil 61401.1SkamilATF_TC_BODY(signal9, tc) 61411.1Skamil{ 61421.1Skamil const int exitval = 5; 61431.1Skamil const int sigval = SIGSTOP; 61441.1Skamil const int sigmasked = SIGTRAP; 61451.1Skamil pid_t child, wpid; 61461.1Skamil#if defined(TWAIT_HAVE_STATUS) 61471.1Skamil int status; 61481.1Skamil#endif 61491.1Skamil sigset_t intmask; 61501.1Skamil ptrace_state_t state; 61511.1Skamil const int slen = sizeof(state); 61521.1Skamil ptrace_event_t event; 61531.1Skamil const int elen = sizeof(event); 61541.1Skamil ucontext_t uc; 61551.1Skamil lwpid_t lid; 61561.1Skamil static const size_t ssize = 16*1024; 61571.1Skamil void *stack; 61581.1Skamil 61591.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 61601.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 61611.1Skamil if (child == 0) { 61621.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 61631.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 61641.1Skamil 61651.1Skamil sigemptyset(&intmask); 61661.1Skamil sigaddset(&intmask, sigmasked); 61671.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 61681.1Skamil 61691.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 61701.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 61711.1Skamil 61721.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 61731.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 61741.1Skamil 61751.13Schristos DPRINTF("Before making context for new lwp in child\n"); 61761.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 61771.1Skamil 61781.13Schristos DPRINTF("Before creating new in child\n"); 61791.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 61801.1Skamil 61811.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 61821.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 61831.1Skamil 61841.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 61851.1Skamil "are the same\n", lid, the_lwp_id); 61861.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 61871.1Skamil 61881.13Schristos DPRINTF("Before exiting of the child process\n"); 61891.1Skamil _exit(exitval); 61901.1Skamil } 61911.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 61921.1Skamil 61931.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 61941.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61951.1Skamil 61961.1Skamil validate_status_stopped(status, sigval); 61971.1Skamil 61981.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 61991.1Skamil event.pe_set_event = PTRACE_LWP_CREATE; 62001.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 62011.1Skamil 62021.13Schristos DPRINTF("Before resuming the child process where it left off and " 62031.1Skamil "without signal to be sent\n"); 62041.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 62051.1Skamil 62061.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 62071.1Skamil "SIGTRAP\n", TWAIT_FNAME); 62081.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62091.1Skamil 62101.1Skamil validate_status_stopped(status, sigmasked); 62111.1Skamil 62121.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 62131.1Skamil 62141.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE); 62151.1Skamil 62161.1Skamil lid = state.pe_lwp; 62171.13Schristos DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 62181.1Skamil 62191.13Schristos DPRINTF("Before resuming the child process where it left off and " 62201.1Skamil "without signal to be sent\n"); 62211.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 62221.1Skamil 62231.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 62241.1Skamil TWAIT_FNAME); 62251.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62261.1Skamil 62271.1Skamil validate_status_exited(status, exitval); 62281.1Skamil 62291.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 62301.1Skamil TWAIT_FNAME); 62311.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 62321.1Skamil} 62331.1Skamil 62341.1SkamilATF_TC(signal10); 62351.1SkamilATF_TC_HEAD(signal10, tc) 62361.1Skamil{ 62371.1Skamil atf_tc_set_md_var(tc, "descr", 62381.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 62391.1Skamil "catching PTRACE_LWP_EXIT breakpoint"); 62401.1Skamil} 62411.1Skamil 62421.1SkamilATF_TC_BODY(signal10, tc) 62431.1Skamil{ 62441.1Skamil const int exitval = 5; 62451.1Skamil const int sigval = SIGSTOP; 62461.1Skamil const int sigmasked = SIGTRAP; 62471.1Skamil pid_t child, wpid; 62481.1Skamil#if defined(TWAIT_HAVE_STATUS) 62491.1Skamil int status; 62501.1Skamil#endif 62511.1Skamil sigset_t intmask; 62521.1Skamil ptrace_state_t state; 62531.1Skamil const int slen = sizeof(state); 62541.1Skamil ptrace_event_t event; 62551.1Skamil const int elen = sizeof(event); 62561.1Skamil ucontext_t uc; 62571.1Skamil lwpid_t lid; 62581.1Skamil static const size_t ssize = 16*1024; 62591.1Skamil void *stack; 62601.1Skamil 62611.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 62621.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 62631.1Skamil if (child == 0) { 62641.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 62651.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 62661.1Skamil 62671.1Skamil sigemptyset(&intmask); 62681.1Skamil sigaddset(&intmask, sigmasked); 62691.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 62701.1Skamil 62711.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 62721.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 62731.1Skamil 62741.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 62751.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 62761.1Skamil 62771.13Schristos DPRINTF("Before making context for new lwp in child\n"); 62781.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 62791.1Skamil 62801.13Schristos DPRINTF("Before creating new in child\n"); 62811.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 62821.1Skamil 62831.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 62841.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 62851.1Skamil 62861.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 62871.1Skamil "are the same\n", lid, the_lwp_id); 62881.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 62891.1Skamil 62901.13Schristos DPRINTF("Before exiting of the child process\n"); 62911.1Skamil _exit(exitval); 62921.1Skamil } 62931.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 62941.1Skamil 62951.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 62961.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62971.1Skamil 62981.1Skamil validate_status_stopped(status, sigval); 62991.1Skamil 63001.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 63011.1Skamil event.pe_set_event = PTRACE_LWP_EXIT; 63021.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 63031.1Skamil 63041.13Schristos DPRINTF("Before resuming the child process where it left off and " 63051.1Skamil "without signal to be sent\n"); 63061.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63071.1Skamil 63081.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 63091.1Skamil "SIGTRAP\n", TWAIT_FNAME); 63101.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63111.1Skamil 63121.1Skamil validate_status_stopped(status, sigmasked); 63131.1Skamil 63141.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 63151.1Skamil 63161.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT); 63171.1Skamil 63181.1Skamil lid = state.pe_lwp; 63191.13Schristos DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 63201.1Skamil 63211.13Schristos DPRINTF("Before resuming the child process where it left off and " 63221.1Skamil "without signal to be sent\n"); 63231.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63241.1Skamil 63251.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 63261.1Skamil TWAIT_FNAME); 63271.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63281.1Skamil 63291.1Skamil validate_status_exited(status, exitval); 63301.1Skamil 63311.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 63321.1Skamil TWAIT_FNAME); 63331.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 63341.1Skamil} 63351.1Skamil 63361.1Skamilstatic void 63371.1Skamillwp_main_stop(void *arg) 63381.1Skamil{ 63391.1Skamil the_lwp_id = _lwp_self(); 63401.1Skamil 63411.1Skamil raise(SIGTRAP); 63421.1Skamil 63431.1Skamil _lwp_exit(); 63441.1Skamil} 63451.1Skamil 63461.1SkamilATF_TC(suspend1); 63471.1SkamilATF_TC_HEAD(suspend1, tc) 63481.1Skamil{ 63491.1Skamil atf_tc_set_md_var(tc, "descr", 63501.1Skamil "Verify that a thread can be suspended by a debugger and later " 63511.1Skamil "resumed by a tracee"); 63521.1Skamil} 63531.1Skamil 63541.1SkamilATF_TC_BODY(suspend1, tc) 63551.1Skamil{ 63561.1Skamil const int exitval = 5; 63571.1Skamil const int sigval = SIGSTOP; 63581.1Skamil pid_t child, wpid; 63591.1Skamil#if defined(TWAIT_HAVE_STATUS) 63601.1Skamil int status; 63611.1Skamil#endif 63621.1Skamil ucontext_t uc; 63631.1Skamil lwpid_t lid; 63641.1Skamil static const size_t ssize = 16*1024; 63651.1Skamil void *stack; 63661.1Skamil struct ptrace_lwpinfo pl; 63671.1Skamil struct ptrace_siginfo psi; 63681.1Skamil volatile int go = 0; 63691.1Skamil 63701.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 63711.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 63721.1Skamil if (child == 0) { 63731.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 63741.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 63751.1Skamil 63761.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 63771.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 63781.1Skamil 63791.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 63801.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 63811.1Skamil 63821.13Schristos DPRINTF("Before making context for new lwp in child\n"); 63831.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 63841.1Skamil 63851.13Schristos DPRINTF("Before creating new in child\n"); 63861.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 63871.1Skamil 63881.1Skamil while (go == 0) 63891.1Skamil continue; 63901.1Skamil 63911.1Skamil raise(SIGINT); 63921.1Skamil 63931.1Skamil FORKEE_ASSERT(_lwp_continue(lid) == 0); 63941.1Skamil 63951.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 63961.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 63971.1Skamil 63981.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 63991.1Skamil "are the same\n", lid, the_lwp_id); 64001.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 64011.1Skamil 64021.13Schristos DPRINTF("Before exiting of the child process\n"); 64031.1Skamil _exit(exitval); 64041.1Skamil } 64051.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 64061.1Skamil 64071.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 64081.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64091.1Skamil 64101.1Skamil validate_status_stopped(status, sigval); 64111.1Skamil 64121.13Schristos DPRINTF("Before resuming the child process where it left off and " 64131.1Skamil "without signal to be sent\n"); 64141.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64151.1Skamil 64161.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 64171.1Skamil "SIGTRAP\n", TWAIT_FNAME); 64181.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64191.1Skamil 64201.1Skamil validate_status_stopped(status, SIGTRAP); 64211.1Skamil 64221.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 64231.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 64241.1Skamil 64251.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 64261.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 64271.1Skamil 64281.13Schristos DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n", 64291.1Skamil child, getpid()); 64301.13Schristos SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1); 64311.1Skamil 64321.13Schristos DPRINTF("Before resuming the child process where it left off and " 64331.1Skamil "without signal to be sent\n"); 64341.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64351.1Skamil 64361.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 64371.1Skamil "SIGINT\n", TWAIT_FNAME); 64381.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64391.1Skamil 64401.1Skamil validate_status_stopped(status, SIGINT); 64411.1Skamil 64421.1Skamil pl.pl_lwpid = 0; 64431.1Skamil 64441.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 64451.1Skamil while (pl.pl_lwpid != 0) { 64461.1Skamil 64471.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 64481.1Skamil switch (pl.pl_lwpid) { 64491.1Skamil case 1: 64501.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 64511.1Skamil break; 64521.1Skamil case 2: 64531.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 64541.1Skamil break; 64551.1Skamil } 64561.1Skamil } 64571.1Skamil 64581.13Schristos DPRINTF("Before resuming the child process where it left off and " 64591.1Skamil "without signal to be sent\n"); 64601.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64611.1Skamil 64621.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 64631.1Skamil TWAIT_FNAME); 64641.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64651.1Skamil 64661.1Skamil validate_status_exited(status, exitval); 64671.1Skamil 64681.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 64691.1Skamil TWAIT_FNAME); 64701.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 64711.1Skamil} 64721.1Skamil 64731.1SkamilATF_TC(suspend2); 64741.1SkamilATF_TC_HEAD(suspend2, tc) 64751.1Skamil{ 64761.1Skamil atf_tc_set_md_var(tc, "descr", 64771.1Skamil "Verify that the while the only thread within a process is " 64781.1Skamil "suspended, the whole process cannot be unstopped"); 64791.1Skamil} 64801.1Skamil 64811.1SkamilATF_TC_BODY(suspend2, tc) 64821.1Skamil{ 64831.1Skamil const int exitval = 5; 64841.1Skamil const int sigval = SIGSTOP; 64851.1Skamil pid_t child, wpid; 64861.1Skamil#if defined(TWAIT_HAVE_STATUS) 64871.1Skamil int status; 64881.1Skamil#endif 64891.1Skamil struct ptrace_siginfo psi; 64901.1Skamil 64911.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 64921.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 64931.1Skamil if (child == 0) { 64941.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 64951.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 64961.1Skamil 64971.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 64981.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 64991.1Skamil 65001.13Schristos DPRINTF("Before exiting of the child process\n"); 65011.1Skamil _exit(exitval); 65021.1Skamil } 65031.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 65041.1Skamil 65051.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65061.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65071.1Skamil 65081.1Skamil validate_status_stopped(status, sigval); 65091.1Skamil 65101.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 65111.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 65121.1Skamil 65131.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 65141.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 65151.1Skamil 65161.13Schristos DPRINTF("Before resuming the child process where it left off and " 65171.1Skamil "without signal to be sent\n"); 65181.1Skamil ATF_REQUIRE_ERRNO(EDEADLK, 65191.1Skamil ptrace(PT_CONTINUE, child, (void *)1, 0) == -1); 65201.1Skamil 65211.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 65221.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 65231.1Skamil 65241.13Schristos DPRINTF("Before resuming the child process where it left off and " 65251.1Skamil "without signal to be sent\n"); 65261.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65271.1Skamil 65281.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 65291.1Skamil TWAIT_FNAME); 65301.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65311.1Skamil 65321.1Skamil validate_status_exited(status, exitval); 65331.1Skamil 65341.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 65351.1Skamil TWAIT_FNAME); 65361.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 65371.1Skamil} 65381.1Skamil 65391.1SkamilATF_TC(resume1); 65401.1SkamilATF_TC_HEAD(resume1, tc) 65411.1Skamil{ 65421.1Skamil atf_tc_set_md_var(tc, "descr", 65431.1Skamil "Verify that a thread can be suspended by a debugger and later " 65441.1Skamil "resumed by the debugger"); 65451.1Skamil} 65461.1Skamil 65471.1SkamilATF_TC_BODY(resume1, tc) 65481.1Skamil{ 65491.1Skamil struct msg_fds fds; 65501.1Skamil const int exitval = 5; 65511.1Skamil const int sigval = SIGSTOP; 65521.1Skamil pid_t child, wpid; 65531.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 65541.1Skamil#if defined(TWAIT_HAVE_STATUS) 65551.1Skamil int status; 65561.1Skamil#endif 65571.1Skamil ucontext_t uc; 65581.1Skamil lwpid_t lid; 65591.1Skamil static const size_t ssize = 16*1024; 65601.1Skamil void *stack; 65611.1Skamil struct ptrace_lwpinfo pl; 65621.1Skamil struct ptrace_siginfo psi; 65631.1Skamil 65641.13Schristos SYSCALL_REQUIRE(msg_open(&fds) == 0); 65651.1Skamil 65661.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 65671.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 65681.1Skamil if (child == 0) { 65691.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 65701.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 65711.1Skamil 65721.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 65731.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 65741.1Skamil 65751.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 65761.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 65771.1Skamil 65781.13Schristos DPRINTF("Before making context for new lwp in child\n"); 65791.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 65801.1Skamil 65811.13Schristos DPRINTF("Before creating new in child\n"); 65821.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 65831.1Skamil 65841.1Skamil CHILD_TO_PARENT("Message", fds, msg); 65851.1Skamil 65861.1Skamil raise(SIGINT); 65871.1Skamil 65881.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 65891.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 65901.1Skamil 65911.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 65921.1Skamil "are the same\n", lid, the_lwp_id); 65931.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 65941.1Skamil 65951.13Schristos DPRINTF("Before exiting of the child process\n"); 65961.1Skamil _exit(exitval); 65971.1Skamil } 65981.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 65991.1Skamil 66001.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66011.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66021.1Skamil 66031.1Skamil validate_status_stopped(status, sigval); 66041.1Skamil 66051.13Schristos DPRINTF("Before resuming the child process where it left off and " 66061.1Skamil "without signal to be sent\n"); 66071.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66081.1Skamil 66091.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 66101.1Skamil "SIGTRAP\n", TWAIT_FNAME); 66111.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66121.1Skamil 66131.1Skamil validate_status_stopped(status, SIGTRAP); 66141.1Skamil 66151.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 66161.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 66171.1Skamil 66181.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 66191.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 66201.1Skamil 66211.1Skamil PARENT_FROM_CHILD("Message", fds, msg); 66221.1Skamil 66231.13Schristos DPRINTF("Before resuming the child process where it left off and " 66241.1Skamil "without signal to be sent\n"); 66251.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66261.1Skamil 66271.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 66281.1Skamil "SIGINT\n", TWAIT_FNAME); 66291.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66301.1Skamil 66311.1Skamil validate_status_stopped(status, SIGINT); 66321.1Skamil 66331.1Skamil pl.pl_lwpid = 0; 66341.1Skamil 66351.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 66361.1Skamil while (pl.pl_lwpid != 0) { 66371.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 66381.1Skamil switch (pl.pl_lwpid) { 66391.1Skamil case 1: 66401.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 66411.1Skamil break; 66421.1Skamil case 2: 66431.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 66441.1Skamil break; 66451.1Skamil } 66461.1Skamil } 66471.1Skamil 66481.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 66491.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 66501.1Skamil 66511.13Schristos DPRINTF("Before resuming the child process where it left off and " 66521.1Skamil "without signal to be sent\n"); 66531.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66541.1Skamil 66551.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 66561.1Skamil TWAIT_FNAME); 66571.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66581.1Skamil 66591.1Skamil validate_status_exited(status, exitval); 66601.1Skamil 66611.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 66621.1Skamil TWAIT_FNAME); 66631.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 66641.1Skamil 66651.1Skamil msg_close(&fds); 66661.1Skamil} 66671.1Skamil 66681.1SkamilATF_TC(syscall1); 66691.1SkamilATF_TC_HEAD(syscall1, tc) 66701.1Skamil{ 66711.1Skamil atf_tc_set_md_var(tc, "descr", 66721.1Skamil "Verify that getpid(2) can be traced with PT_SYSCALL"); 66731.1Skamil} 66741.1Skamil 66751.1SkamilATF_TC_BODY(syscall1, tc) 66761.1Skamil{ 66771.1Skamil const int exitval = 5; 66781.1Skamil const int sigval = SIGSTOP; 66791.1Skamil pid_t child, wpid; 66801.1Skamil#if defined(TWAIT_HAVE_STATUS) 66811.1Skamil int status; 66821.1Skamil#endif 66831.1Skamil struct ptrace_siginfo info; 66841.1Skamil memset(&info, 0, sizeof(info)); 66851.1Skamil 66861.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 66871.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 66881.1Skamil if (child == 0) { 66891.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 66901.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 66911.1Skamil 66921.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 66931.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 66941.1Skamil 66951.1Skamil syscall(SYS_getpid); 66961.1Skamil 66971.13Schristos DPRINTF("Before exiting of the child process\n"); 66981.1Skamil _exit(exitval); 66991.1Skamil } 67001.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 67011.1Skamil 67021.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67031.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67041.1Skamil 67051.1Skamil validate_status_stopped(status, sigval); 67061.1Skamil 67071.13Schristos DPRINTF("Before resuming the child process where it left off and " 67081.1Skamil "without signal to be sent\n"); 67091.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 67101.1Skamil 67111.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67121.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67131.1Skamil 67141.1Skamil validate_status_stopped(status, SIGTRAP); 67151.1Skamil 67161.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 67171.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 67181.1Skamil 67191.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 67201.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 67211.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 67221.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE); 67231.1Skamil 67241.13Schristos DPRINTF("Before resuming the child process where it left off and " 67251.1Skamil "without signal to be sent\n"); 67261.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 67271.1Skamil 67281.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67291.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67301.1Skamil 67311.1Skamil validate_status_stopped(status, SIGTRAP); 67321.1Skamil 67331.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 67341.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 67351.1Skamil 67361.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 67371.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 67381.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 67391.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX); 67401.1Skamil 67411.13Schristos DPRINTF("Before resuming the child process where it left off and " 67421.1Skamil "without signal to be sent\n"); 67431.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 67441.1Skamil 67451.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67461.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67471.1Skamil 67481.1Skamil validate_status_exited(status, exitval); 67491.1Skamil 67501.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67511.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 67521.1Skamil} 67531.1Skamil 67541.1SkamilATF_TC(syscallemu1); 67551.1SkamilATF_TC_HEAD(syscallemu1, tc) 67561.1Skamil{ 67571.1Skamil atf_tc_set_md_var(tc, "descr", 67581.1Skamil "Verify that exit(2) can be intercepted with PT_SYSCALLEMU"); 67591.1Skamil} 67601.1Skamil 67611.1SkamilATF_TC_BODY(syscallemu1, tc) 67621.1Skamil{ 67631.1Skamil const int exitval = 5; 67641.1Skamil const int sigval = SIGSTOP; 67651.1Skamil pid_t child, wpid; 67661.1Skamil#if defined(TWAIT_HAVE_STATUS) 67671.1Skamil int status; 67681.1Skamil#endif 67691.1Skamil 67701.6Skamil#if defined(__sparc__) && !defined(__sparc64__) 67711.6Skamil /* syscallemu does not work on sparc (32-bit) */ 67721.6Skamil atf_tc_expect_fail("PR kern/52166"); 67731.6Skamil#endif 67741.6Skamil 67751.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 67761.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 67771.1Skamil if (child == 0) { 67781.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 67791.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 67801.1Skamil 67811.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 67821.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 67831.1Skamil 67841.1Skamil syscall(SYS_exit, 100); 67851.1Skamil 67861.13Schristos DPRINTF("Before exiting of the child process\n"); 67871.1Skamil _exit(exitval); 67881.1Skamil } 67891.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 67901.1Skamil 67911.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67921.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67931.1Skamil 67941.1Skamil validate_status_stopped(status, sigval); 67951.1Skamil 67961.13Schristos DPRINTF("Before resuming the child process where it left off and " 67971.1Skamil "without signal to be sent\n"); 67981.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 67991.1Skamil 68001.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 68011.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68021.1Skamil 68031.1Skamil validate_status_stopped(status, SIGTRAP); 68041.1Skamil 68051.13Schristos DPRINTF("Set SYSCALLEMU for intercepted syscall\n"); 68061.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1); 68071.1Skamil 68081.13Schristos DPRINTF("Before resuming the child process where it left off and " 68091.1Skamil "without signal to be sent\n"); 68101.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 68111.1Skamil 68121.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 68131.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68141.1Skamil 68151.1Skamil validate_status_stopped(status, SIGTRAP); 68161.1Skamil 68171.13Schristos DPRINTF("Before resuming the child process where it left off and " 68181.1Skamil "without signal to be sent\n"); 68191.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68201.1Skamil 68211.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 68221.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68231.1Skamil 68241.1Skamil validate_status_exited(status, exitval); 68251.1Skamil 68261.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 68271.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 68281.1Skamil} 68291.1Skamil 68301.103Skamil/// ---------------------------------------------------------------------------- 68311.103Skamil 68321.106Skamilstatic void 68331.106Skamilclone_body(int flags, bool trackfork, bool trackvfork, 68341.106Skamil bool trackvforkdone) 68351.106Skamil{ 68361.106Skamil const int exitval = 5; 68371.106Skamil const int exitval2 = 15; 68381.106Skamil const int sigval = SIGSTOP; 68391.106Skamil pid_t child, child2 = 0, wpid; 68401.106Skamil#if defined(TWAIT_HAVE_STATUS) 68411.106Skamil int status; 68421.106Skamil#endif 68431.106Skamil ptrace_state_t state; 68441.106Skamil const int slen = sizeof(state); 68451.106Skamil ptrace_event_t event; 68461.106Skamil const int elen = sizeof(event); 68471.106Skamil 68481.106Skamil const size_t stack_size = 1024 * 1024; 68491.106Skamil void *stack, *stack_base; 68501.106Skamil 68511.106Skamil stack = malloc(stack_size); 68521.106Skamil ATF_REQUIRE(stack != NULL); 68531.106Skamil 68541.106Skamil#ifdef __MACHINE_STACK_GROWS_UP 68551.106Skamil stack_base = stack; 68561.106Skamil#else 68571.106Skamil stack_base = (char *)stack + stack_size; 68581.106Skamil#endif 68591.106Skamil 68601.106Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 68611.106Skamil SYSCALL_REQUIRE((child = fork()) != -1); 68621.106Skamil if (child == 0) { 68631.106Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 68641.106Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 68651.106Skamil 68661.106Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 68671.106Skamil FORKEE_ASSERT(raise(sigval) == 0); 68681.106Skamil 68691.106Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 68701.106Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 68711.106Skamil 68721.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 68731.106Skamil child2); 68741.106Skamil 68751.106Skamil // XXX WALLSIG? 68761.106Skamil FORKEE_REQUIRE_SUCCESS 68771.106Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 68781.106Skamil 68791.106Skamil forkee_status_exited(status, exitval2); 68801.106Skamil 68811.106Skamil DPRINTF("Before exiting of the child process\n"); 68821.106Skamil _exit(exitval); 68831.106Skamil } 68841.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 68851.106Skamil 68861.106Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 68871.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68881.106Skamil 68891.106Skamil validate_status_stopped(status, sigval); 68901.106Skamil 68911.106Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 68921.106Skamil trackfork ? "|PTRACE_FORK" : "", 68931.106Skamil trackvfork ? "|PTRACE_VFORK" : "", 68941.106Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 68951.106Skamil event.pe_set_event = 0; 68961.106Skamil if (trackfork) 68971.106Skamil event.pe_set_event |= PTRACE_FORK; 68981.106Skamil if (trackvfork) 68991.106Skamil event.pe_set_event |= PTRACE_VFORK; 69001.106Skamil if (trackvforkdone) 69011.106Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 69021.106Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 69031.106Skamil 69041.106Skamil DPRINTF("Before resuming the child process where it left off and " 69051.106Skamil "without signal to be sent\n"); 69061.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69071.106Skamil 69081.106Skamil#if defined(TWAIT_HAVE_PID) 69091.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 69101.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 69111.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 69121.106Skamil child); 69131.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 69141.106Skamil child); 69151.106Skamil 69161.106Skamil validate_status_stopped(status, SIGTRAP); 69171.106Skamil 69181.106Skamil SYSCALL_REQUIRE( 69191.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 69201.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 69211.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 69221.106Skamil PTRACE_FORK); 69231.106Skamil } 69241.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 69251.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 69261.106Skamil PTRACE_VFORK); 69271.106Skamil } 69281.106Skamil 69291.106Skamil child2 = state.pe_other_pid; 69301.106Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 69311.106Skamil 69321.106Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 69331.106Skamil "%d\n", TWAIT_FNAME, child2, child); 69341.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 69351.106Skamil child2); 69361.106Skamil 69371.106Skamil validate_status_stopped(status, SIGTRAP); 69381.106Skamil 69391.106Skamil SYSCALL_REQUIRE( 69401.106Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 69411.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 69421.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 69431.106Skamil PTRACE_FORK); 69441.106Skamil } 69451.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 69461.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 69471.106Skamil PTRACE_VFORK); 69481.106Skamil } 69491.106Skamil 69501.106Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 69511.106Skamil 69521.106Skamil DPRINTF("Before resuming the forkee process where it left off " 69531.106Skamil "and without signal to be sent\n"); 69541.106Skamil SYSCALL_REQUIRE( 69551.106Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 69561.106Skamil 69571.106Skamil DPRINTF("Before resuming the child process where it left off " 69581.106Skamil "and without signal to be sent\n"); 69591.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69601.106Skamil } 69611.106Skamil#endif 69621.106Skamil 69631.106Skamil if (trackvforkdone && (flags & CLONE_VFORK)) { 69641.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 69651.106Skamil child); 69661.106Skamil TWAIT_REQUIRE_SUCCESS( 69671.106Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 69681.106Skamil 69691.106Skamil validate_status_stopped(status, SIGTRAP); 69701.106Skamil 69711.106Skamil SYSCALL_REQUIRE( 69721.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 69731.106Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 69741.106Skamil 69751.106Skamil child2 = state.pe_other_pid; 69761.106Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 69771.106Skamil child2); 69781.106Skamil 69791.106Skamil DPRINTF("Before resuming the child process where it left off " 69801.106Skamil "and without signal to be sent\n"); 69811.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69821.106Skamil } 69831.106Skamil 69841.103Skamil#if defined(TWAIT_HAVE_PID) 69851.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 69861.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 69871.106Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 69881.106Skamil "\n", TWAIT_FNAME); 69891.106Skamil TWAIT_REQUIRE_SUCCESS( 69901.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 69911.106Skamil 69921.106Skamil validate_status_exited(status, exitval2); 69931.106Skamil 69941.106Skamil DPRINTF("Before calling %s() for the forkee - expected no " 69951.106Skamil "process\n", TWAIT_FNAME); 69961.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 69971.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 69981.106Skamil } 69991.106Skamil#endif 70001.106Skamil 70011.106Skamil DPRINTF("Before calling %s() for the child - expected stopped " 70021.106Skamil "SIGCHLD\n", TWAIT_FNAME); 70031.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 70041.106Skamil 70051.106Skamil validate_status_stopped(status, SIGCHLD); 70061.106Skamil 70071.106Skamil DPRINTF("Before resuming the child process where it left off and " 70081.106Skamil "without signal to be sent\n"); 70091.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 70101.106Skamil 70111.106Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 70121.106Skamil TWAIT_FNAME); 70131.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 70141.106Skamil 70151.106Skamil validate_status_exited(status, exitval); 70161.103Skamil 70171.106Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 70181.106Skamil TWAIT_FNAME); 70191.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 70201.106Skamil} 70211.103Skamil 70221.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone) \ 70231.106SkamilATF_TC(name); \ 70241.106SkamilATF_TC_HEAD(name, tc) \ 70251.106Skamil{ \ 70261.106Skamil atf_tc_set_md_var(tc, "descr", "Verify clone(%s) " \ 70271.106Skamil "called with 0%s%s%s in EVENT_MASK", \ 70281.106Skamil #flags, \ 70291.106Skamil tfork ? "|PTRACE_FORK" : "", \ 70301.106Skamil tvfork ? "|PTRACE_VFORK" : "", \ 70311.106Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 70321.106Skamil} \ 70331.106Skamil \ 70341.106SkamilATF_TC_BODY(name, tc) \ 70351.106Skamil{ \ 70361.106Skamil \ 70371.106Skamil clone_body(flags, tfork, tvfork, tvforkdone); \ 70381.103Skamil} 70391.103Skamil 70401.106SkamilCLONE_TEST(clone1, 0, false, false, false) 70411.106Skamil#if defined(TWAIT_HAVE_PID) 70421.106SkamilCLONE_TEST(clone2, 0, true, false, false) 70431.106SkamilCLONE_TEST(clone3, 0, false, true, false) 70441.106SkamilCLONE_TEST(clone4, 0, true, true, false) 70451.106Skamil#endif 70461.106SkamilCLONE_TEST(clone5, 0, false, false, true) 70471.106Skamil#if defined(TWAIT_HAVE_PID) 70481.106SkamilCLONE_TEST(clone6, 0, true, false, true) 70491.106SkamilCLONE_TEST(clone7, 0, false, true, true) 70501.106SkamilCLONE_TEST(clone8, 0, true, true, true) 70511.106Skamil#endif 70521.106Skamil 70531.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false) 70541.106Skamil#if defined(TWAIT_HAVE_PID) 70551.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false) 70561.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false) 70571.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false) 70581.106Skamil#endif 70591.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true) 70601.106Skamil#if defined(TWAIT_HAVE_PID) 70611.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true) 70621.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true) 70631.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true) 70641.106Skamil#endif 70651.106Skamil 70661.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false) 70671.106Skamil#if defined(TWAIT_HAVE_PID) 70681.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false) 70691.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false) 70701.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false) 70711.106Skamil#endif 70721.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true) 70731.106Skamil#if defined(TWAIT_HAVE_PID) 70741.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true) 70751.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true) 70761.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true) 70771.106Skamil#endif 70781.106Skamil 70791.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false) 70801.106Skamil#if defined(TWAIT_HAVE_PID) 70811.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false) 70821.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false) 70831.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false) 70841.106Skamil#endif 70851.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true) 70861.106Skamil#if defined(TWAIT_HAVE_PID) 70871.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true) 70881.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true) 70891.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true) 70901.106Skamil#endif 70911.106Skamil 70921.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false) 70931.106Skamil#if defined(TWAIT_HAVE_PID) 70941.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false) 70951.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false) 70961.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false) 70971.106Skamil#endif 70981.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true) 70991.106Skamil#if defined(TWAIT_HAVE_PID) 71001.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true) 71011.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true) 71021.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true) 71031.106Skamil#endif 71041.106Skamil 71051.110Skamil#if TEST_VFORK_ENABLED 71061.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false) 71071.106Skamil#if defined(TWAIT_HAVE_PID) 71081.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false) 71091.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false) 71101.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false) 71111.106Skamil#endif 71121.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true) 71131.106Skamil#if defined(TWAIT_HAVE_PID) 71141.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true) 71151.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true) 71161.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true) 71171.106Skamil#endif 71181.110Skamil#endif 71191.106Skamil 71201.106Skamil/// ---------------------------------------------------------------------------- 71211.106Skamil 71221.106Skamil#if defined(TWAIT_HAVE_PID) 71231.103Skamilstatic void 71241.106Skamilclone_body2(int flags, bool masked, bool ignored) 71251.103Skamil{ 71261.103Skamil const int exitval = 5; 71271.103Skamil const int exitval2 = 15; 71281.103Skamil const int sigval = SIGSTOP; 71291.103Skamil pid_t child, child2 = 0, wpid; 71301.103Skamil#if defined(TWAIT_HAVE_STATUS) 71311.103Skamil int status; 71321.103Skamil#endif 71331.103Skamil ptrace_state_t state; 71341.103Skamil const int slen = sizeof(state); 71351.103Skamil ptrace_event_t event; 71361.103Skamil const int elen = sizeof(event); 71371.103Skamil struct sigaction sa; 71381.103Skamil struct ptrace_siginfo info; 71391.103Skamil sigset_t intmask; 71401.103Skamil struct kinfo_proc2 kp; 71411.103Skamil size_t len = sizeof(kp); 71421.103Skamil 71431.103Skamil int name[6]; 71441.103Skamil const size_t namelen = __arraycount(name); 71451.103Skamil ki_sigset_t kp_sigmask; 71461.103Skamil ki_sigset_t kp_sigignore; 71471.103Skamil 71481.103Skamil const size_t stack_size = 1024 * 1024; 71491.103Skamil void *stack, *stack_base; 71501.103Skamil 71511.103Skamil stack = malloc(stack_size); 71521.103Skamil ATF_REQUIRE(stack != NULL); 71531.103Skamil 71541.103Skamil#ifdef __MACHINE_STACK_GROWS_UP 71551.103Skamil stack_base = stack; 71561.103Skamil#else 71571.103Skamil stack_base = (char *)stack + stack_size; 71581.103Skamil#endif 71591.103Skamil 71601.103Skamil SYSCALL_REQUIRE((child = fork()) != -1); 71611.103Skamil if (child == 0) { 71621.103Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 71631.103Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 71641.103Skamil 71651.103Skamil if (masked) { 71661.103Skamil sigemptyset(&intmask); 71671.103Skamil sigaddset(&intmask, SIGTRAP); 71681.103Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 71691.103Skamil } 71701.103Skamil 71711.103Skamil if (ignored) { 71721.103Skamil memset(&sa, 0, sizeof(sa)); 71731.103Skamil sa.sa_handler = SIG_IGN; 71741.103Skamil sigemptyset(&sa.sa_mask); 71751.103Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 71761.103Skamil } 71771.103Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 71781.103Skamil FORKEE_ASSERT(raise(sigval) == 0); 71791.103Skamil 71801.103Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 71811.103Skamil flags); 71821.103Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 71831.103Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 71841.103Skamil 71851.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 71861.103Skamil child2); 71871.103Skamil 71881.103Skamil // XXX WALLSIG? 71891.103Skamil FORKEE_REQUIRE_SUCCESS 71901.103Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 71911.103Skamil 71921.103Skamil forkee_status_exited(status, exitval2); 71931.103Skamil 71941.103Skamil DPRINTF("Before exiting of the child process\n"); 71951.103Skamil _exit(exitval); 71961.103Skamil } 71971.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 71981.103Skamil 71991.103Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 72001.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 72011.103Skamil 72021.103Skamil validate_status_stopped(status, sigval); 72031.103Skamil 72041.103Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 72051.103Skamil SYSCALL_REQUIRE( 72061.103Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 72071.103Skamil 72081.103Skamil DPRINTF("Before checking siginfo_t\n"); 72091.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 72101.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 72111.103Skamil 72121.103Skamil name[0] = CTL_KERN, 72131.103Skamil name[1] = KERN_PROC2, 72141.103Skamil name[2] = KERN_PROC_PID; 72151.103Skamil name[3] = child; 72161.103Skamil name[4] = sizeof(kp); 72171.103Skamil name[5] = 1; 72181.103Skamil 72191.103Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 72201.103Skamil 72211.103Skamil if (masked) 72221.103Skamil kp_sigmask = kp.p_sigmask; 72231.103Skamil 72241.103Skamil if (ignored) 72251.103Skamil kp_sigignore = kp.p_sigignore; 72261.103Skamil 72271.103Skamil DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in " 72281.103Skamil "EVENT_MASK for the child %d\n", child); 72291.103Skamil event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE; 72301.103Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 72311.103Skamil 72321.103Skamil DPRINTF("Before resuming the child process where it left off and " 72331.103Skamil "without signal to be sent\n"); 72341.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 72351.103Skamil 72361.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 72371.103Skamil child); 72381.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 72391.103Skamil child); 72401.103Skamil 72411.103Skamil validate_status_stopped(status, SIGTRAP); 72421.103Skamil 72431.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 72441.103Skamil 72451.103Skamil if (masked) { 72461.103Skamil DPRINTF("kp_sigmask=" 72471.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72481.103Skamil PRIx32 "\n", 72491.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 72501.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 72511.103Skamil 72521.103Skamil DPRINTF("kp.p_sigmask=" 72531.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72541.103Skamil PRIx32 "\n", 72551.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 72561.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 72571.103Skamil 72581.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 72591.103Skamil sizeof(kp_sigmask))); 72601.103Skamil } 72611.103Skamil 72621.103Skamil if (ignored) { 72631.103Skamil DPRINTF("kp_sigignore=" 72641.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72651.103Skamil PRIx32 "\n", 72661.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 72671.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 72681.103Skamil 72691.103Skamil DPRINTF("kp.p_sigignore=" 72701.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72711.103Skamil PRIx32 "\n", 72721.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 72731.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 72741.103Skamil 72751.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 72761.103Skamil sizeof(kp_sigignore))); 72771.103Skamil } 72781.103Skamil 72791.103Skamil SYSCALL_REQUIRE( 72801.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 72811.103Skamil DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event, 72821.103Skamil child2); 72831.103Skamil if (!(flags & CLONE_VFORK)) { 72841.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 72851.103Skamil PTRACE_FORK); 72861.103Skamil } else { 72871.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 72881.103Skamil PTRACE_VFORK); 72891.103Skamil } 72901.103Skamil 72911.103Skamil child2 = state.pe_other_pid; 72921.103Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 72931.103Skamil 72941.103Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 72951.103Skamil "%d\n", TWAIT_FNAME, child2, child); 72961.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 72971.103Skamil child2); 72981.103Skamil 72991.103Skamil validate_status_stopped(status, SIGTRAP); 73001.103Skamil 73011.103Skamil name[3] = child2; 73021.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 73031.103Skamil 73041.103Skamil if (masked) { 73051.103Skamil DPRINTF("kp_sigmask=" 73061.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73071.103Skamil PRIx32 "\n", 73081.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 73091.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 73101.103Skamil 73111.103Skamil DPRINTF("kp.p_sigmask=" 73121.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73131.103Skamil PRIx32 "\n", 73141.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 73151.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 73161.103Skamil 73171.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 73181.103Skamil sizeof(kp_sigmask))); 73191.103Skamil } 73201.103Skamil 73211.103Skamil if (ignored) { 73221.103Skamil DPRINTF("kp_sigignore=" 73231.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73241.103Skamil PRIx32 "\n", 73251.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 73261.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 73271.103Skamil 73281.103Skamil DPRINTF("kp.p_sigignore=" 73291.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73301.103Skamil PRIx32 "\n", 73311.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 73321.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 73331.103Skamil 73341.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 73351.103Skamil sizeof(kp_sigignore))); 73361.103Skamil } 73371.103Skamil 73381.103Skamil SYSCALL_REQUIRE( 73391.103Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 73401.103Skamil if (!(flags & CLONE_VFORK)) { 73411.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 73421.103Skamil PTRACE_FORK); 73431.103Skamil } else { 73441.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 73451.103Skamil PTRACE_VFORK); 73461.103Skamil } 73471.103Skamil 73481.103Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 73491.103Skamil 73501.103Skamil DPRINTF("Before resuming the forkee process where it left off " 73511.103Skamil "and without signal to be sent\n"); 73521.103Skamil SYSCALL_REQUIRE( 73531.103Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 73541.103Skamil 73551.103Skamil DPRINTF("Before resuming the child process where it left off " 73561.103Skamil "and without signal to be sent\n"); 73571.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 73581.103Skamil 73591.103Skamil if (flags & CLONE_VFORK) { 73601.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 73611.103Skamil child); 73621.103Skamil TWAIT_REQUIRE_SUCCESS( 73631.103Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 73641.103Skamil 73651.103Skamil validate_status_stopped(status, SIGTRAP); 73661.103Skamil 73671.103Skamil name[3] = child; 73681.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 73691.103Skamil 73701.103Skamil /* 73711.103Skamil * SIGCHLD is now pending in the signal queue and 73721.103Skamil * the kernel presents it to userland as a masked signal. 73731.103Skamil */ 73741.103Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 73751.103Skamil 73761.103Skamil if (masked) { 73771.103Skamil DPRINTF("kp_sigmask=" 73781.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73791.103Skamil PRIx32 "\n", 73801.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 73811.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 73821.103Skamil 73831.103Skamil DPRINTF("kp.p_sigmask=" 73841.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73851.103Skamil PRIx32 "\n", 73861.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 73871.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 73881.103Skamil 73891.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 73901.103Skamil sizeof(kp_sigmask))); 73911.103Skamil } 73921.103Skamil 73931.103Skamil if (ignored) { 73941.103Skamil DPRINTF("kp_sigignore=" 73951.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73961.103Skamil PRIx32 "\n", 73971.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 73981.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 73991.103Skamil 74001.103Skamil DPRINTF("kp.p_sigignore=" 74011.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 74021.103Skamil PRIx32 "\n", 74031.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 74041.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 74051.103Skamil 74061.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 74071.103Skamil sizeof(kp_sigignore))); 74081.103Skamil } 74091.103Skamil 74101.103Skamil SYSCALL_REQUIRE( 74111.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 74121.103Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 74131.103Skamil 74141.103Skamil child2 = state.pe_other_pid; 74151.103Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 74161.103Skamil child2); 74171.103Skamil 74181.103Skamil DPRINTF("Before resuming the child process where it left off " 74191.103Skamil "and without signal to be sent\n"); 74201.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 74211.103Skamil } 74221.103Skamil 74231.103Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 74241.103Skamil "\n", TWAIT_FNAME); 74251.103Skamil TWAIT_REQUIRE_SUCCESS( 74261.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 74271.103Skamil 74281.103Skamil validate_status_exited(status, exitval2); 74291.103Skamil 74301.103Skamil DPRINTF("Before calling %s() for the forkee - expected no " 74311.103Skamil "process\n", TWAIT_FNAME); 74321.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 74331.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 74341.103Skamil 74351.103Skamil DPRINTF("Before calling %s() for the child - expected stopped " 74361.103Skamil "SIGCHLD\n", TWAIT_FNAME); 74371.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74381.103Skamil 74391.103Skamil validate_status_stopped(status, SIGCHLD); 74401.103Skamil 74411.103Skamil DPRINTF("Before resuming the child process where it left off and " 74421.103Skamil "without signal to be sent\n"); 74431.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 74441.103Skamil 74451.103Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 74461.103Skamil TWAIT_FNAME); 74471.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74481.103Skamil 74491.103Skamil validate_status_exited(status, exitval); 74501.103Skamil 74511.103Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 74521.103Skamil TWAIT_FNAME); 74531.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 74541.103Skamil} 74551.103Skamil 74561.106Skamil#define CLONE_TEST2(name,flags,masked,ignored) \ 74571.103SkamilATF_TC(name); \ 74581.103SkamilATF_TC_HEAD(name, tc) \ 74591.103Skamil{ \ 74601.103Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\ 74611.103Skamil " regardless of signal %s%s", \ 74621.103Skamil #flags, masked ? "masked" : "", ignored ? "ignored" : ""); \ 74631.103Skamil} \ 74641.103Skamil \ 74651.103SkamilATF_TC_BODY(name, tc) \ 74661.103Skamil{ \ 74671.103Skamil \ 74681.106Skamil clone_body2(flags, masked, ignored); \ 74691.103Skamil} 74701.103Skamil 74711.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false) 74721.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true) 74731.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false) 74741.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true) 74751.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false) 74761.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true) 74771.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false) 74781.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true) 74791.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX 74801.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true) // XXX 74811.110Skamil#if TEST_VFORK_ENABLED 74821.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false) 74831.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true) 74841.103Skamil#endif 74851.110Skamil#endif 74861.103Skamil 74871.103Skamil/// ---------------------------------------------------------------------------- 74881.103Skamil 74891.111Skamil#if TEST_VFORK_ENABLED 74901.107Skamil#if defined(TWAIT_HAVE_PID) 74911.107Skamilstatic void 74921.107Skamiltraceme_vfork_clone_body(int flags) 74931.107Skamil{ 74941.107Skamil const int exitval = 5; 74951.107Skamil const int exitval2 = 15; 74961.107Skamil pid_t child, child2 = 0, wpid; 74971.107Skamil#if defined(TWAIT_HAVE_STATUS) 74981.107Skamil int status; 74991.107Skamil#endif 75001.107Skamil 75011.107Skamil const size_t stack_size = 1024 * 1024; 75021.107Skamil void *stack, *stack_base; 75031.107Skamil 75041.107Skamil stack = malloc(stack_size); 75051.107Skamil ATF_REQUIRE(stack != NULL); 75061.107Skamil 75071.107Skamil#ifdef __MACHINE_STACK_GROWS_UP 75081.107Skamil stack_base = stack; 75091.107Skamil#else 75101.107Skamil stack_base = (char *)stack + stack_size; 75111.107Skamil#endif 75121.107Skamil 75131.107Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 75141.107Skamil if (child == 0) { 75151.107Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 75161.107Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 75171.107Skamil 75181.107Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 75191.107Skamil flags); 75201.107Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 75211.107Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 75221.107Skamil 75231.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 75241.107Skamil child2); 75251.107Skamil 75261.107Skamil // XXX WALLSIG? 75271.107Skamil FORKEE_REQUIRE_SUCCESS 75281.107Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 75291.107Skamil 75301.107Skamil forkee_status_exited(status, exitval2); 75311.107Skamil 75321.107Skamil DPRINTF("Before exiting of the child process\n"); 75331.107Skamil _exit(exitval); 75341.107Skamil } 75351.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 75361.107Skamil 75371.107Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 75381.107Skamil TWAIT_FNAME); 75391.107Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75401.107Skamil 75411.107Skamil validate_status_exited(status, exitval); 75421.107Skamil 75431.107Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 75441.107Skamil TWAIT_FNAME); 75451.107Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 75461.107Skamil} 75471.107Skamil 75481.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags) \ 75491.107SkamilATF_TC(name); \ 75501.107SkamilATF_TC_HEAD(name, tc) \ 75511.107Skamil{ \ 75521.107Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is " \ 75531.107Skamil "handled correctly with vfork(2)ed tracer", \ 75541.107Skamil #flags); \ 75551.107Skamil} \ 75561.107Skamil \ 75571.107SkamilATF_TC_BODY(name, tc) \ 75581.107Skamil{ \ 75591.107Skamil \ 75601.107Skamil traceme_vfork_clone_body(flags); \ 75611.107Skamil} 75621.107Skamil 75631.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0) 75641.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM) 75651.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS) 75661.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES) 75671.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND) // XXX 75681.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK) 75691.107Skamil#endif 75701.110Skamil#endif 75711.107Skamil 75721.107Skamil/// ---------------------------------------------------------------------------- 75731.107Skamil 75741.122Skamilstatic void 75751.122Skamiluser_va0_disable(int operation) 75761.122Skamil{ 75771.122Skamil pid_t child, wpid; 75781.122Skamil#if defined(TWAIT_HAVE_STATUS) 75791.122Skamil int status; 75801.122Skamil#endif 75811.122Skamil const int sigval = SIGSTOP; 75821.122Skamil int rv; 75831.122Skamil 75841.122Skamil struct ptrace_siginfo info; 75851.122Skamil 75861.122Skamil if (get_user_va0_disable() == 0) 75871.122Skamil atf_tc_skip("vm.user_va0_disable is set to 0"); 75881.122Skamil 75891.122Skamil memset(&info, 0, sizeof(info)); 75901.122Skamil 75911.122Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 75921.122Skamil SYSCALL_REQUIRE((child = fork()) != -1); 75931.122Skamil if (child == 0) { 75941.122Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 75951.122Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 75961.122Skamil 75971.122Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 75981.122Skamil FORKEE_ASSERT(raise(sigval) == 0); 75991.122Skamil 76001.122Skamil /* NOTREACHED */ 76011.122Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 76021.122Skamil __unreachable(); 76031.122Skamil } 76041.122Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 76051.122Skamil 76061.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76071.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 76081.122Skamil 76091.122Skamil validate_status_stopped(status, sigval); 76101.122Skamil 76111.122Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 76121.122Skamil "child\n"); 76131.122Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 76141.122Skamil sizeof(info)) != -1); 76151.122Skamil 76161.122Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 76171.122Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 76181.122Skamil "si_errno=%#x\n", 76191.122Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 76201.122Skamil info.psi_siginfo.si_errno); 76211.122Skamil 76221.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 76231.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 76241.122Skamil 76251.122Skamil DPRINTF("Before resuming the child process in PC=0x0 " 76261.122Skamil "and without signal to be sent\n"); 76271.122Skamil errno = 0; 76281.122Skamil rv = ptrace(operation, child, (void *)0, 0); 76291.122Skamil ATF_REQUIRE_EQ(errno, EINVAL); 76301.122Skamil ATF_REQUIRE_EQ(rv, -1); 76311.122Skamil 76321.122Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 76331.122Skamil 76341.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76351.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 76361.122Skamil validate_status_signaled(status, SIGKILL, 0); 76371.122Skamil 76381.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76391.122Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 76401.122Skamil} 76411.122Skamil 76421.122Skamil#define USER_VA0_DISABLE(test, operation) \ 76431.122SkamilATF_TC(test); \ 76441.122SkamilATF_TC_HEAD(test, tc) \ 76451.122Skamil{ \ 76461.122Skamil atf_tc_set_md_var(tc, "descr", \ 76471.122Skamil "Verify behavior of " #operation " with PC set to 0x0"); \ 76481.122Skamil} \ 76491.122Skamil \ 76501.122SkamilATF_TC_BODY(test, tc) \ 76511.122Skamil{ \ 76521.122Skamil \ 76531.122Skamil user_va0_disable(operation); \ 76541.122Skamil} 76551.122Skamil 76561.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE) 76571.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL) 76581.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH) 76591.122Skamil 76601.122Skamil/// ---------------------------------------------------------------------------- 76611.122Skamil 76621.130Smgorny/* 76631.130Smgorny * Parse the core file and find the requested note. If the reading or parsing 76641.130Smgorny * fails, the test is failed. If the note is found, it is read onto buf, up to 76651.130Smgorny * buf_len. The actual length of the note is returned (which can be greater 76661.130Smgorny * than buf_len, indicating that it has been truncated). If the note is not 76671.130Smgorny * found, -1 is returned. 76681.130Smgorny */ 76691.130Smgornystatic ssize_t core_find_note(const char *core_path, 76701.130Smgorny const char *note_name, uint64_t note_type, void *buf, size_t buf_len) 76711.130Smgorny{ 76721.130Smgorny int core_fd; 76731.130Smgorny Elf *core_elf; 76741.130Smgorny size_t core_numhdr, i; 76751.130Smgorny ssize_t ret = -1; 76761.130Smgorny /* note: we assume note name will be null-terminated */ 76771.130Smgorny size_t name_len = strlen(note_name) + 1; 76781.130Smgorny 76791.130Smgorny SYSCALL_REQUIRE((core_fd = open(core_path, O_RDONLY)) != -1); 76801.130Smgorny SYSCALL_REQUIRE(elf_version(EV_CURRENT) != EV_NONE); 76811.130Smgorny SYSCALL_REQUIRE((core_elf = elf_begin(core_fd, ELF_C_READ, NULL))); 76821.130Smgorny 76831.130Smgorny SYSCALL_REQUIRE(elf_getphnum(core_elf, &core_numhdr) != 0); 76841.130Smgorny for (i = 0; i < core_numhdr && ret == -1; i++) { 76851.130Smgorny GElf_Phdr core_hdr; 76861.130Smgorny size_t offset; 76871.130Smgorny SYSCALL_REQUIRE(gelf_getphdr(core_elf, i, &core_hdr)); 76881.130Smgorny if (core_hdr.p_type != PT_NOTE) 76891.130Smgorny continue; 76901.130Smgorny 76911.130Smgorny for (offset = core_hdr.p_offset; 76921.130Smgorny offset < core_hdr.p_offset + core_hdr.p_filesz;) { 76931.130Smgorny Elf64_Nhdr note_hdr; 76941.130Smgorny char name_buf[64]; 76951.130Smgorny 76961.130Smgorny switch (gelf_getclass(core_elf)) { 76971.130Smgorny case ELFCLASS64: 76981.130Smgorny SYSCALL_REQUIRE(pread(core_fd, ¬e_hdr, 76991.130Smgorny sizeof(note_hdr), offset) 77001.130Smgorny == sizeof(note_hdr)); 77011.130Smgorny offset += sizeof(note_hdr); 77021.130Smgorny break; 77031.130Smgorny case ELFCLASS32: 77041.130Smgorny { 77051.130Smgorny Elf32_Nhdr tmp_hdr; 77061.130Smgorny SYSCALL_REQUIRE(pread(core_fd, &tmp_hdr, 77071.130Smgorny sizeof(tmp_hdr), offset) 77081.130Smgorny == sizeof(tmp_hdr)); 77091.130Smgorny offset += sizeof(tmp_hdr); 77101.130Smgorny note_hdr.n_namesz = tmp_hdr.n_namesz; 77111.130Smgorny note_hdr.n_descsz = tmp_hdr.n_descsz; 77121.130Smgorny note_hdr.n_type = tmp_hdr.n_type; 77131.130Smgorny } 77141.130Smgorny break; 77151.130Smgorny } 77161.130Smgorny 77171.130Smgorny /* indicates end of notes */ 77181.130Smgorny if (note_hdr.n_namesz == 0 || note_hdr.n_descsz == 0) 77191.130Smgorny break; 77201.130Smgorny if (note_hdr.n_namesz == name_len && 77211.130Smgorny note_hdr.n_namesz <= sizeof(name_buf)) { 77221.130Smgorny SYSCALL_REQUIRE(pread(core_fd, name_buf, 77231.130Smgorny note_hdr.n_namesz, offset) 77241.131Skamil == (ssize_t)(size_t)note_hdr.n_namesz); 77251.130Smgorny 77261.130Smgorny if (!strncmp(note_name, name_buf, name_len) && 77271.130Smgorny note_hdr.n_type == note_type) 77281.130Smgorny ret = note_hdr.n_descsz; 77291.130Smgorny } 77301.130Smgorny 77311.130Smgorny offset += note_hdr.n_namesz; 77321.130Smgorny /* fix to alignment */ 77331.130Smgorny offset = ((offset + core_hdr.p_align - 1) 77341.130Smgorny / core_hdr.p_align) * core_hdr.p_align; 77351.130Smgorny 77361.130Smgorny /* if name & type matched above */ 77371.130Smgorny if (ret != -1) { 77381.130Smgorny ssize_t read_len = MIN(buf_len, 77391.130Smgorny note_hdr.n_descsz); 77401.130Smgorny SYSCALL_REQUIRE(pread(core_fd, buf, 77411.130Smgorny read_len, offset) == read_len); 77421.130Smgorny break; 77431.130Smgorny } 77441.130Smgorny 77451.130Smgorny offset += note_hdr.n_descsz; 77461.130Smgorny } 77471.130Smgorny } 77481.130Smgorny 77491.130Smgorny elf_end(core_elf); 77501.130Smgorny close(core_fd); 77511.130Smgorny 77521.130Smgorny return ret; 77531.130Smgorny} 77541.130Smgorny 77551.130SmgornyATF_TC(core_dump_procinfo); 77561.130SmgornyATF_TC_HEAD(core_dump_procinfo, tc) 77571.130Smgorny{ 77581.130Smgorny atf_tc_set_md_var(tc, "descr", 77591.130Smgorny "Trigger a core dump and verify its contents."); 77601.130Smgorny} 77611.130Smgorny 77621.130SmgornyATF_TC_BODY(core_dump_procinfo, tc) 77631.130Smgorny{ 77641.130Smgorny const int exitval = 5; 77651.130Smgorny pid_t child, wpid; 77661.130Smgorny#if defined(TWAIT_HAVE_STATUS) 77671.130Smgorny const int sigval = SIGTRAP; 77681.130Smgorny int status; 77691.130Smgorny#endif 77701.130Smgorny char core_path[] = "/tmp/core.XXXXXX"; 77711.130Smgorny int core_fd; 77721.130Smgorny struct netbsd_elfcore_procinfo procinfo; 77731.130Smgorny 77741.130Smgorny DPRINTF("Before forking process PID=%d\n", getpid()); 77751.130Smgorny SYSCALL_REQUIRE((child = fork()) != -1); 77761.130Smgorny if (child == 0) { 77771.130Smgorny DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 77781.130Smgorny FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 77791.130Smgorny 77801.130Smgorny DPRINTF("Before triggering SIGTRAP\n"); 77811.130Smgorny trigger_trap(); 77821.130Smgorny 77831.130Smgorny DPRINTF("Before exiting of the child process\n"); 77841.130Smgorny _exit(exitval); 77851.130Smgorny } 77861.130Smgorny DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 77871.130Smgorny 77881.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 77891.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 77901.130Smgorny 77911.130Smgorny validate_status_stopped(status, sigval); 77921.130Smgorny 77931.130Smgorny SYSCALL_REQUIRE((core_fd = mkstemp(core_path)) != -1); 77941.130Smgorny close(core_fd); 77951.130Smgorny 77961.130Smgorny DPRINTF("Call DUMPCORE for the child process\n"); 77971.130Smgorny SYSCALL_REQUIRE(ptrace(PT_DUMPCORE, child, core_path, strlen(core_path)) 77981.130Smgorny != -1); 77991.130Smgorny 78001.130Smgorny DPRINTF("Read core file\n"); 78011.130Smgorny ATF_REQUIRE_EQ(core_find_note(core_path, "NetBSD-CORE", 78021.130Smgorny ELF_NOTE_NETBSD_CORE_PROCINFO, &procinfo, sizeof(procinfo)), 78031.130Smgorny sizeof(procinfo)); 78041.130Smgorny 78051.130Smgorny ATF_CHECK_EQ(procinfo.cpi_version, 1); 78061.130Smgorny ATF_CHECK_EQ(procinfo.cpi_cpisize, sizeof(procinfo)); 78071.130Smgorny ATF_CHECK_EQ(procinfo.cpi_signo, SIGTRAP); 78081.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pid, child); 78091.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ppid, getpid()); 78101.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pgrp, getpgid(child)); 78111.130Smgorny ATF_CHECK_EQ(procinfo.cpi_sid, getsid(child)); 78121.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ruid, getuid()); 78131.130Smgorny ATF_CHECK_EQ(procinfo.cpi_euid, geteuid()); 78141.130Smgorny ATF_CHECK_EQ(procinfo.cpi_rgid, getgid()); 78151.130Smgorny ATF_CHECK_EQ(procinfo.cpi_egid, getegid()); 78161.130Smgorny ATF_CHECK_EQ(procinfo.cpi_nlwps, 1); 78171.130Smgorny ATF_CHECK_EQ(procinfo.cpi_siglwp, 1); 78181.130Smgorny 78191.130Smgorny unlink(core_path); 78201.130Smgorny 78211.130Smgorny DPRINTF("Before resuming the child process where it left off and " 78221.130Smgorny "without signal to be sent\n"); 78231.130Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 78241.130Smgorny 78251.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 78261.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 78271.130Smgorny 78281.130Smgorny validate_status_exited(status, exitval); 78291.130Smgorny 78301.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 78311.130Smgorny TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 78321.130Smgorny} 78331.130Smgorny 78341.130Smgorny/// ---------------------------------------------------------------------------- 78351.130Smgorny 78361.1Skamil#include "t_ptrace_amd64_wait.h" 78371.1Skamil#include "t_ptrace_i386_wait.h" 78381.1Skamil#include "t_ptrace_x86_wait.h" 78391.1Skamil 78401.1SkamilATF_TP_ADD_TCS(tp) 78411.1Skamil{ 78421.1Skamil setvbuf(stdout, NULL, _IONBF, 0); 78431.1Skamil setvbuf(stderr, NULL, _IONBF, 0); 78441.33Skamil 78451.36Skamil ATF_TP_ADD_TC(tp, traceme_raise1); 78461.33Skamil ATF_TP_ADD_TC(tp, traceme_raise2); 78471.33Skamil ATF_TP_ADD_TC(tp, traceme_raise3); 78481.33Skamil ATF_TP_ADD_TC(tp, traceme_raise4); 78491.33Skamil ATF_TP_ADD_TC(tp, traceme_raise5); 78501.85Skamil ATF_TP_ADD_TC(tp, traceme_raise6); 78511.85Skamil ATF_TP_ADD_TC(tp, traceme_raise7); 78521.85Skamil ATF_TP_ADD_TC(tp, traceme_raise8); 78531.85Skamil ATF_TP_ADD_TC(tp, traceme_raise9); 78541.85Skamil ATF_TP_ADD_TC(tp, traceme_raise10); 78551.33Skamil 78561.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1); 78571.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2); 78581.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3); 78591.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4); 78601.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5); 78611.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6); 78621.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7); 78631.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8); 78641.87Skamil 78651.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1); 78661.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2); 78671.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3); 78681.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4); 78691.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5); 78701.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6); 78711.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7); 78721.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8); 78731.86Skamil 78741.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_trap); 78751.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_segv); 78761.71Skamil ATF_TP_ADD_TC(tp, traceme_crash_ill); 78771.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_fpe); 78781.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_bus); 78791.59Skamil 78801.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap); 78811.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv); 78821.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill); 78831.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe); 78841.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus); 78851.88Skamil 78861.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap); 78871.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv); 78881.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill); 78891.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe); 78901.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus); 78911.88Skamil 78921.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1); 78931.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2); 78941.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3); 78951.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4); 78961.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5); 78971.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6); 78981.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7); 78991.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8); 79001.50Skamil 79011.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1); 79021.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2); 79031.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3); 79041.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4); 79051.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5); 79061.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6); 79071.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7); 79081.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8); 79091.50Skamil 79101.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1); 79111.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2); 79121.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3); 79131.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4); 79141.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5); 79151.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6); 79161.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7); 79171.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8); 79181.50Skamil 79191.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1); 79201.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2); 79211.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3); 79221.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4); 79231.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5); 79241.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6); 79251.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7); 79261.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8); 79271.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9); 79281.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10); 79291.1Skamil 79301.37Skamil ATF_TP_ADD_TC(tp, traceme_pid1_parent); 79311.37Skamil 79321.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise1); 79331.46Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise2); 79341.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise3); 79351.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise4); 79361.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise5); 79371.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise6); 79381.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise7); 79391.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise8); 79401.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise9); 79411.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise10); 79421.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise11); 79431.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise12); 79441.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise13); 79451.40Skamil 79461.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap); 79471.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv); 79481.71Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill); 79491.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe); 79501.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus); 79511.41Skamil 79521.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap); 79531.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv); 79541.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill); 79551.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe); 79561.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus); 79571.92Skamil 79581.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap); 79591.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv); 79601.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill); 79611.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe); 79621.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus); 79631.92Skamil 79641.43Skamil ATF_TP_ADD_TC(tp, traceme_vfork_exec); 79651.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec); 79661.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec); 79671.43Skamil 79681.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap); 79691.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv); 79701.71Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill); 79711.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe); 79721.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus); 79731.59Skamil 79741.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79751.94Skamil unrelated_tracer_sees_signalmasked_crash_trap); 79761.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79771.94Skamil unrelated_tracer_sees_signalmasked_crash_segv); 79781.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79791.94Skamil unrelated_tracer_sees_signalmasked_crash_ill); 79801.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79811.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe); 79821.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79831.94Skamil unrelated_tracer_sees_signalmasked_crash_bus); 79841.94Skamil 79851.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79861.94Skamil unrelated_tracer_sees_signalignored_crash_trap); 79871.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79881.94Skamil unrelated_tracer_sees_signalignored_crash_segv); 79891.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79901.94Skamil unrelated_tracer_sees_signalignored_crash_ill); 79911.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79921.94Skamil unrelated_tracer_sees_signalignored_crash_fpe); 79931.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 79941.94Skamil unrelated_tracer_sees_signalignored_crash_bus); 79951.94Skamil 79961.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent); 79971.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates); 79981.61Skre ATF_TP_ADD_TC_HAVE_PID(tp, 79991.61Skre unrelated_tracer_sees_terminaton_before_the_parent); 80001.67Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process); 80011.51Skamil 80021.51Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_child); 80031.66Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child); 80041.51Skamil 80051.51Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_parent); 80061.65Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent); 80071.51Skamil 80081.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 80091.51Skamil tracee_sees_its_original_parent_getppid); 80101.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 80111.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2); 80121.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 80131.51Skamil tracee_sees_its_original_parent_procfs_status); 80141.1Skamil 80151.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_empty); 80161.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_fork); 80171.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork); 80181.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done); 80191.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create); 80201.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit); 80211.125Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_posix_spawn); 80221.1Skamil 80231.31Skamil ATF_TP_ADD_TC(tp, fork1); 80241.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork2); 80251.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork3); 80261.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork4); 80271.31Skamil ATF_TP_ADD_TC(tp, fork5); 80281.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork6); 80291.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork7); 80301.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork8); 80311.125Skamil ATF_TP_ADD_TC(tp, fork9); 80321.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork10); 80331.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork11); 80341.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork12); 80351.125Skamil ATF_TP_ADD_TC(tp, fork13); 80361.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork14); 80371.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork15); 80381.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork16); 80391.31Skamil 80401.109Skamil#if TEST_VFORK_ENABLED 80411.31Skamil ATF_TP_ADD_TC(tp, vfork1); 80421.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork2); 80431.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork3); 80441.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork4); 80451.31Skamil ATF_TP_ADD_TC(tp, vfork5); 80461.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork6); 80471.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork7); 80481.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork8); 80491.125Skamil ATF_TP_ADD_TC(tp, vfork9); 80501.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork10); 80511.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork11); 80521.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork12); 80531.125Skamil ATF_TP_ADD_TC(tp, vfork13); 80541.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork14); 80551.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork15); 80561.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork16); 80571.116Skamil#endif 80581.1Skamil 80591.124Skamil ATF_TP_ADD_TC(tp, posix_spawn1); 80601.125Skamil ATF_TP_ADD_TC(tp, posix_spawn2); 80611.125Skamil ATF_TP_ADD_TC(tp, posix_spawn3); 80621.125Skamil ATF_TP_ADD_TC(tp, posix_spawn4); 80631.124Skamil ATF_TP_ADD_TC(tp, posix_spawn5); 80641.125Skamil ATF_TP_ADD_TC(tp, posix_spawn6); 80651.125Skamil ATF_TP_ADD_TC(tp, posix_spawn7); 80661.125Skamil ATF_TP_ADD_TC(tp, posix_spawn8); 80671.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn9); 80681.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn10); 80691.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn11); 80701.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn12); 80711.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn13); 80721.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn14); 80731.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn15); 80741.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn16); 80751.124Skamil 80761.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_detach_spawner); 80771.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_detach_forker); 80781.116Skamil#if TEST_VFORK_ENABLED 80791.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforker); 80801.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforkerdone); 80811.116Skamil#endif 80821.126Skamil 80831.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_kill_spawner); 80841.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_kill_forker); 80851.116Skamil#if TEST_VFORK_ENABLED 80861.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforker); 80871.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforkerdone); 80881.116Skamil#endif 80891.116Skamil 80901.116Skamil#if TEST_VFORK_ENABLED 80911.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_fork); 80921.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_vfork); 80931.109Skamil#endif 80941.108Skamil 80951.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8); 80961.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16); 80971.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32); 80981.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64); 80991.54Skamil 81001.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8); 81011.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16); 81021.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32); 81031.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64); 81041.54Skamil 81051.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8); 81061.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16); 81071.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32); 81081.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64); 81091.54Skamil 81101.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8); 81111.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16); 81121.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32); 81131.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64); 81141.54Skamil 81151.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d); 81161.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i); 81171.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d); 81181.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i); 81191.54Skamil 81201.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text); 81211.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text); 81221.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text); 81231.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text); 81241.54Skamil 81251.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text); 81261.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text); 81271.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text); 81281.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text); 81291.54Skamil 81301.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text); 81311.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text); 81321.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text); 81331.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text); 81341.54Skamil 81351.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text); 81361.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text); 81371.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text); 81381.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text); 81391.54Skamil 81401.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text); 81411.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text); 81421.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text); 81431.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text); 81441.1Skamil 81451.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv); 81461.1Skamil 81471.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i); 81481.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d); 81491.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i); 81501.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d); 81511.101Skamil 81521.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i); 81531.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d); 81541.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i); 81551.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d); 81561.101Skamil 81571.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv); 81581.101Skamil 81591.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i); 81601.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d); 81611.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i); 81621.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d); 81631.115Skamil 81641.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i); 81651.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d); 81661.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i); 81671.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d); 81681.115Skamil 81691.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1); 81701.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2); 81711.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3); 81721.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4); 81731.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5); 81741.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6); 81751.1Skamil 81761.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1); 81771.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2); 81781.1Skamil 81791.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step1); 81801.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step2); 81811.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step3); 81821.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step4); 81831.1Skamil 81841.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep1); 81851.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep2); 81861.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep3); 81871.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep4); 81881.2Skamil 81891.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked); 81901.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored); 81911.95Skamil 81921.1Skamil ATF_TP_ADD_TC(tp, kill1); 81931.1Skamil ATF_TP_ADD_TC(tp, kill2); 81941.75Skamil ATF_TP_ADD_TC(tp, kill3); 81951.1Skamil 81961.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0); 81971.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1); 81981.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2); 81991.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3); 82001.77Skamil 82011.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0); 82021.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1); 82031.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2); 82041.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3); 82051.1Skamil 82061.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_unmodified); 82071.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_faked); 82081.79Skamil 82091.82Skamil ATF_TP_ADD_TC(tp, traceme_exec); 82101.97Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_exec); 82111.97Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_exec); 82121.1Skamil 82131.119Skamil ATF_TP_ADD_TC(tp, trace_thread_nolwpevents); 82141.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpexit); 82151.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate); 82161.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit); 82171.1Skamil 82181.84Skamil ATF_TP_ADD_TC(tp, signal_mask_unrelated); 82191.84Skamil 82201.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalmasked); 82211.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalignored); 82221.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked); 82231.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored); 82241.109Skamil#if TEST_VFORK_ENABLED 82251.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked); 82261.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored); 82271.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked); 82281.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored); 82291.109Skamil#endif 82301.99Skamil 82311.1Skamil ATF_TP_ADD_TC(tp, signal9); 82321.1Skamil ATF_TP_ADD_TC(tp, signal10); 82331.1Skamil 82341.1Skamil ATF_TP_ADD_TC(tp, suspend1); 82351.1Skamil ATF_TP_ADD_TC(tp, suspend2); 82361.1Skamil 82371.1Skamil ATF_TP_ADD_TC(tp, resume1); 82381.1Skamil 82391.1Skamil ATF_TP_ADD_TC(tp, syscall1); 82401.1Skamil 82411.1Skamil ATF_TP_ADD_TC(tp, syscallemu1); 82421.1Skamil 82431.106Skamil ATF_TP_ADD_TC(tp, clone1); 82441.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone2); 82451.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone3); 82461.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone4); 82471.106Skamil ATF_TP_ADD_TC(tp, clone5); 82481.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone6); 82491.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone7); 82501.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone8); 82511.106Skamil 82521.106Skamil ATF_TP_ADD_TC(tp, clone_vm1); 82531.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2); 82541.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3); 82551.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4); 82561.106Skamil ATF_TP_ADD_TC(tp, clone_vm5); 82571.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6); 82581.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7); 82591.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8); 82601.106Skamil 82611.106Skamil ATF_TP_ADD_TC(tp, clone_fs1); 82621.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2); 82631.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3); 82641.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4); 82651.106Skamil ATF_TP_ADD_TC(tp, clone_fs5); 82661.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6); 82671.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7); 82681.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8); 82691.106Skamil 82701.106Skamil ATF_TP_ADD_TC(tp, clone_files1); 82711.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2); 82721.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3); 82731.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4); 82741.106Skamil ATF_TP_ADD_TC(tp, clone_files5); 82751.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6); 82761.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7); 82771.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8); 82781.106Skamil 82791.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand1); // XXX 82801.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX 82811.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX 82821.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX 82831.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand5); // XXX 82841.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX 82851.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX 82861.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX 82871.106Skamil 82881.109Skamil#if TEST_VFORK_ENABLED 82891.106Skamil ATF_TP_ADD_TC(tp, clone_vfork1); 82901.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2); 82911.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3); 82921.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4); 82931.106Skamil ATF_TP_ADD_TC(tp, clone_vfork5); 82941.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6); 82951.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7); 82961.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8); 82971.109Skamil#endif 82981.106Skamil 82991.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored); 83001.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked); 83011.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored); 83021.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked); 83031.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored); 83041.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked); 83051.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored); 83061.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked); 83071.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX 83081.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX 83091.109Skamil#if TEST_VFORK_ENABLED 83101.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored); 83111.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked); 83121.109Skamil#endif 83131.103Skamil 83141.109Skamil#if TEST_VFORK_ENABLED 83151.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone); 83161.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm); 83171.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs); 83181.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files); 83191.107Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX 83201.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork); 83211.109Skamil#endif 83221.107Skamil 83231.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue); 83241.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall); 83251.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach); 83261.122Skamil 83271.130Smgorny ATF_TP_ADD_TC(tp, core_dump_procinfo); 83281.130Smgorny 83291.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64(); 83301.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_I386(); 83311.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_X86(); 83321.1Skamil 83331.1Skamil return atf_no_error(); 83341.1Skamil} 8335