t_ptrace_wait.c revision 1.127
11.127Skamil/* $NetBSD: t_ptrace_wait.c,v 1.127 2019/06/13 20:26:06 kamil Exp $ */ 21.1Skamil 31.1Skamil/*- 41.78Skamil * Copyright (c) 2016, 2017, 2018, 2019 The NetBSD Foundation, Inc. 51.1Skamil * All rights reserved. 61.1Skamil * 71.1Skamil * Redistribution and use in source and binary forms, with or without 81.1Skamil * modification, are permitted provided that the following conditions 91.1Skamil * are met: 101.1Skamil * 1. Redistributions of source code must retain the above copyright 111.1Skamil * notice, this list of conditions and the following disclaimer. 121.1Skamil * 2. Redistributions in binary form must reproduce the above copyright 131.1Skamil * notice, this list of conditions and the following disclaimer in the 141.1Skamil * documentation and/or other materials provided with the distribution. 151.1Skamil * 161.1Skamil * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 171.1Skamil * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 181.1Skamil * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 191.1Skamil * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 201.1Skamil * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 211.1Skamil * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 221.1Skamil * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 231.1Skamil * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 241.1Skamil * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 251.1Skamil * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 261.1Skamil * POSSIBILITY OF SUCH DAMAGE. 271.1Skamil */ 281.1Skamil 291.1Skamil#include <sys/cdefs.h> 301.127Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.127 2019/06/13 20:26:06 kamil Exp $"); 311.1Skamil 321.1Skamil#include <sys/param.h> 331.1Skamil#include <sys/types.h> 341.39Skamil#include <sys/mman.h> 351.1Skamil#include <sys/ptrace.h> 361.1Skamil#include <sys/resource.h> 371.1Skamil#include <sys/stat.h> 381.1Skamil#include <sys/syscall.h> 391.1Skamil#include <sys/sysctl.h> 401.1Skamil#include <sys/wait.h> 411.1Skamil#include <machine/reg.h> 421.1Skamil#include <elf.h> 431.1Skamil#include <err.h> 441.1Skamil#include <errno.h> 451.1Skamil#include <lwp.h> 461.77Skamil#include <pthread.h> 471.1Skamil#include <sched.h> 481.1Skamil#include <signal.h> 491.124Skamil#include <spawn.h> 501.1Skamil#include <stdint.h> 511.1Skamil#include <stdio.h> 521.1Skamil#include <stdlib.h> 531.1Skamil#include <strings.h> 541.26Skamil#include <time.h> 551.1Skamil#include <unistd.h> 561.1Skamil 571.114Skamil#include <fenv.h> 581.114Skamil#if (__arm__ && !__SOFTFP__) || __aarch64__ 591.114Skamil#include <ieeefp.h> /* only need for ARM Cortex/Neon hack */ 601.114Skamil#endif 611.114Skamil 621.121Smgorny#if defined(__i386__) || defined(__x86_64__) 631.121Smgorny#include <cpuid.h> 641.121Smgorny#include <x86/cpu_extended_state.h> 651.121Smgorny#endif 661.121Smgorny 671.1Skamil#include <atf-c.h> 681.1Skamil 691.1Skamil#include "h_macros.h" 701.1Skamil 711.1Skamil#include "t_ptrace_wait.h" 721.1Skamil#include "msg.h" 731.1Skamil 741.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \ 751.61Skre SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \ 761.61Skre sizeof(msg)) == 0) 771.1Skamil 781.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \ 791.61Skre FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \ 801.61Skre sizeof(msg)) == 0) 811.1Skamil 821.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \ 831.61Skre FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \ 841.61Skre sizeof(msg)) == 0) 851.1Skamil 861.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \ 871.61Skre SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \ 881.61Skre sizeof(msg)) == 0) 891.13Schristos 901.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \ 911.13Schristos strerror(errno)) 921.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \ 931.18Schristos "%d(%s) != %d", res, strerror(res), exp) 941.13Schristos 951.13Schristosstatic int debug = 0; 961.13Schristos 971.13Schristos#define DPRINTF(a, ...) do \ 981.123Skamil if (debug) \ 991.123Skamil printf("%s() %s:%d " a, __func__, __FILE__, __LINE__, ##__VA_ARGS__); \ 1001.13Schristos while (/*CONSTCOND*/0) 1011.1Skamil 1021.110Skamil#ifndef TEST_VFORK_ENABLED 1031.127Skamil#define TEST_VFORK_ENABLED 1 1041.110Skamil#endif 1051.109Skamil 1061.34Skamil/// ---------------------------------------------------------------------------- 1071.34Skamil 1081.33Skamilstatic void 1091.33Skamiltraceme_raise(int sigval) 1101.1Skamil{ 1111.1Skamil const int exitval = 5; 1121.1Skamil pid_t child, wpid; 1131.1Skamil#if defined(TWAIT_HAVE_STATUS) 1141.1Skamil int status; 1151.1Skamil#endif 1161.1Skamil 1171.45Skamil struct ptrace_siginfo info; 1181.45Skamil memset(&info, 0, sizeof(info)); 1191.45Skamil 1201.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 1211.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 1221.1Skamil if (child == 0) { 1231.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1241.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1251.1Skamil 1261.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1271.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 1281.1Skamil 1291.36Skamil switch (sigval) { 1301.36Skamil case SIGKILL: 1311.36Skamil /* NOTREACHED */ 1321.36Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 1331.70Smrg __unreachable(); 1341.36Skamil default: 1351.36Skamil DPRINTF("Before exiting of the child process\n"); 1361.36Skamil _exit(exitval); 1371.36Skamil } 1381.1Skamil } 1391.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1401.1Skamil 1411.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1421.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1431.1Skamil 1441.36Skamil switch (sigval) { 1451.36Skamil case SIGKILL: 1461.36Skamil validate_status_signaled(status, sigval, 0); 1471.36Skamil break; 1481.36Skamil default: 1491.36Skamil validate_status_stopped(status, sigval); 1501.1Skamil 1511.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 1521.61Skre "child\n"); 1531.45Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 1541.61Skre sizeof(info)) != -1); 1551.45Skamil 1561.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1571.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 1581.61Skre "si_errno=%#x\n", 1591.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1601.61Skre info.psi_siginfo.si_errno); 1611.45Skamil 1621.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 1631.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 1641.45Skamil 1651.36Skamil DPRINTF("Before resuming the child process where it left off " 1661.36Skamil "and without signal to be sent\n"); 1671.36Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1681.1Skamil 1691.36Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1701.36Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 1711.61Skre child); 1721.36Skamil break; 1731.36Skamil } 1741.1Skamil 1751.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1761.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 1771.1Skamil} 1781.1Skamil 1791.61Skre#define TRACEME_RAISE(test, sig) \ 1801.61SkreATF_TC(test); \ 1811.61SkreATF_TC_HEAD(test, tc) \ 1821.61Skre{ \ 1831.61Skre atf_tc_set_md_var(tc, "descr", \ 1841.61Skre "Verify " #sig " followed by _exit(2) in a child"); \ 1851.61Skre} \ 1861.61Skre \ 1871.61SkreATF_TC_BODY(test, tc) \ 1881.61Skre{ \ 1891.61Skre \ 1901.61Skre traceme_raise(sig); \ 1911.33Skamil} 1921.33Skamil 1931.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */ 1941.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */ 1951.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */ 1961.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP) /* hangup */ 1971.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */ 1981.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */ 1991.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */ 2001.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */ 2011.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */ 2021.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */ 2031.33Skamil 2041.34Skamil/// ---------------------------------------------------------------------------- 2051.1Skamil 2061.1Skamilstatic void 2071.87Skamiltraceme_raisesignal_ignored(int sigignored) 2081.87Skamil{ 2091.87Skamil const int exitval = 5; 2101.87Skamil const int sigval = SIGSTOP; 2111.87Skamil pid_t child, wpid; 2121.87Skamil struct sigaction sa; 2131.87Skamil#if defined(TWAIT_HAVE_STATUS) 2141.87Skamil int status; 2151.87Skamil#endif 2161.87Skamil struct ptrace_siginfo info; 2171.87Skamil 2181.87Skamil memset(&info, 0, sizeof(info)); 2191.87Skamil 2201.87Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 2211.87Skamil SYSCALL_REQUIRE((child = fork()) != -1); 2221.87Skamil if (child == 0) { 2231.87Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2241.87Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2251.87Skamil 2261.87Skamil memset(&sa, 0, sizeof(sa)); 2271.87Skamil sa.sa_handler = SIG_IGN; 2281.87Skamil sigemptyset(&sa.sa_mask); 2291.87Skamil FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1); 2301.87Skamil 2311.87Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 2321.87Skamil FORKEE_ASSERT(raise(sigval) == 0); 2331.87Skamil 2341.87Skamil DPRINTF("Before raising %s from child\n", 2351.87Skamil strsignal(sigignored)); 2361.87Skamil FORKEE_ASSERT(raise(sigignored) == 0); 2371.87Skamil 2381.87Skamil DPRINTF("Before exiting of the child process\n"); 2391.87Skamil _exit(exitval); 2401.87Skamil } 2411.87Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2421.87Skamil 2431.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2441.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2451.87Skamil 2461.87Skamil validate_status_stopped(status, sigval); 2471.87Skamil 2481.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2491.87Skamil SYSCALL_REQUIRE( 2501.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2511.87Skamil 2521.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2531.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2541.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2551.87Skamil info.psi_siginfo.si_errno); 2561.87Skamil 2571.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 2581.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2591.87Skamil 2601.87Skamil DPRINTF("Before resuming the child process where it left off and " 2611.87Skamil "without signal to be sent\n"); 2621.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2631.87Skamil 2641.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2651.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2661.87Skamil 2671.87Skamil validate_status_stopped(status, sigignored); 2681.87Skamil 2691.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2701.87Skamil SYSCALL_REQUIRE( 2711.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2721.87Skamil 2731.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2741.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2751.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2761.87Skamil info.psi_siginfo.si_errno); 2771.87Skamil 2781.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored); 2791.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2801.87Skamil 2811.87Skamil DPRINTF("Before resuming the child process where it left off and " 2821.87Skamil "without signal to be sent\n"); 2831.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2841.87Skamil 2851.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2861.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2871.87Skamil 2881.87Skamil validate_status_exited(status, exitval); 2891.87Skamil 2901.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2911.87Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 2921.87Skamil} 2931.87Skamil 2941.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig) \ 2951.87SkamilATF_TC(test); \ 2961.87SkamilATF_TC_HEAD(test, tc) \ 2971.87Skamil{ \ 2981.87Skamil atf_tc_set_md_var(tc, "descr", \ 2991.87Skamil "Verify that ignoring (with SIG_IGN) " #sig " in tracee " \ 3001.87Skamil "does not stop tracer from catching this raised signal"); \ 3011.87Skamil} \ 3021.87Skamil \ 3031.87SkamilATF_TC_BODY(test, tc) \ 3041.87Skamil{ \ 3051.87Skamil \ 3061.87Skamil traceme_raisesignal_ignored(sig); \ 3071.87Skamil} 3081.87Skamil 3091.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 3101.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */ 3111.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP) /* hangup */ 3121.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */ 3131.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */ 3141.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */ 3151.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */ 3161.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */ 3171.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */ 3181.87Skamil 3191.87Skamil/// ---------------------------------------------------------------------------- 3201.87Skamil 3211.87Skamilstatic void 3221.86Skamiltraceme_raisesignal_masked(int sigmasked) 3231.86Skamil{ 3241.86Skamil const int exitval = 5; 3251.86Skamil const int sigval = SIGSTOP; 3261.86Skamil pid_t child, wpid; 3271.86Skamil#if defined(TWAIT_HAVE_STATUS) 3281.86Skamil int status; 3291.86Skamil#endif 3301.86Skamil sigset_t intmask; 3311.86Skamil struct ptrace_siginfo info; 3321.86Skamil 3331.86Skamil memset(&info, 0, sizeof(info)); 3341.86Skamil 3351.86Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 3361.86Skamil SYSCALL_REQUIRE((child = fork()) != -1); 3371.86Skamil if (child == 0) { 3381.86Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 3391.86Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 3401.86Skamil 3411.86Skamil sigemptyset(&intmask); 3421.86Skamil sigaddset(&intmask, sigmasked); 3431.86Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 3441.86Skamil 3451.86Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 3461.86Skamil FORKEE_ASSERT(raise(sigval) == 0); 3471.86Skamil 3481.86Skamil DPRINTF("Before raising %s breakpoint from child\n", 3491.86Skamil strsignal(sigmasked)); 3501.86Skamil FORKEE_ASSERT(raise(sigmasked) == 0); 3511.86Skamil 3521.86Skamil DPRINTF("Before exiting of the child process\n"); 3531.86Skamil _exit(exitval); 3541.86Skamil } 3551.86Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 3561.86Skamil 3571.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3581.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3591.86Skamil 3601.86Skamil validate_status_stopped(status, sigval); 3611.86Skamil 3621.86Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 3631.86Skamil SYSCALL_REQUIRE( 3641.86Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 3651.86Skamil 3661.86Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 3671.86Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 3681.86Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 3691.86Skamil info.psi_siginfo.si_errno); 3701.86Skamil 3711.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 3721.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 3731.86Skamil 3741.86Skamil DPRINTF("Before resuming the child process where it left off and " 3751.86Skamil "without signal to be sent\n"); 3761.86Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 3771.86Skamil 3781.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3791.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3801.86Skamil 3811.86Skamil validate_status_exited(status, exitval); 3821.86Skamil 3831.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3841.86Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 3851.86Skamil} 3861.86Skamil 3871.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig) \ 3881.86SkamilATF_TC(test); \ 3891.86SkamilATF_TC_HEAD(test, tc) \ 3901.86Skamil{ \ 3911.86Skamil atf_tc_set_md_var(tc, "descr", \ 3921.86Skamil "Verify that masking (with SIG_BLOCK) " #sig " in tracee " \ 3931.86Skamil "stops tracer from catching this raised signal"); \ 3941.86Skamil} \ 3951.86Skamil \ 3961.86SkamilATF_TC_BODY(test, tc) \ 3971.86Skamil{ \ 3981.86Skamil \ 3991.86Skamil traceme_raisesignal_masked(sig); \ 4001.86Skamil} 4011.86Skamil 4021.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 4031.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */ 4041.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP) /* hangup */ 4051.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */ 4061.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */ 4071.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */ 4081.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */ 4091.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */ 4101.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */ 4111.86Skamil 4121.86Skamil/// ---------------------------------------------------------------------------- 4131.86Skamil 4141.86Skamilstatic void 4151.59Skamiltraceme_crash(int sig) 4161.59Skamil{ 4171.59Skamil pid_t child, wpid; 4181.59Skamil#if defined(TWAIT_HAVE_STATUS) 4191.59Skamil int status; 4201.59Skamil#endif 4211.59Skamil struct ptrace_siginfo info; 4221.61Skre 4231.71Skamil#ifndef PTRACE_ILLEGAL_ASM 4241.71Skamil if (sig == SIGILL) 4251.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 4261.71Skamil#endif 4271.71Skamil 4281.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 4291.114Skamil atf_tc_skip("FP exceptions are not supported"); 4301.114Skamil 4311.59Skamil memset(&info, 0, sizeof(info)); 4321.59Skamil 4331.59Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 4341.59Skamil SYSCALL_REQUIRE((child = fork()) != -1); 4351.59Skamil if (child == 0) { 4361.59Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 4371.59Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 4381.59Skamil 4391.59Skamil DPRINTF("Before executing a trap\n"); 4401.59Skamil switch (sig) { 4411.59Skamil case SIGTRAP: 4421.59Skamil trigger_trap(); 4431.59Skamil break; 4441.59Skamil case SIGSEGV: 4451.59Skamil trigger_segv(); 4461.59Skamil break; 4471.59Skamil case SIGILL: 4481.59Skamil trigger_ill(); 4491.59Skamil break; 4501.59Skamil case SIGFPE: 4511.59Skamil trigger_fpe(); 4521.59Skamil break; 4531.59Skamil case SIGBUS: 4541.59Skamil trigger_bus(); 4551.59Skamil break; 4561.59Skamil default: 4571.59Skamil /* NOTREACHED */ 4581.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4591.59Skamil } 4601.59Skamil 4611.59Skamil /* NOTREACHED */ 4621.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4631.59Skamil } 4641.59Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 4651.59Skamil 4661.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4671.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4681.59Skamil 4691.59Skamil validate_status_stopped(status, sig); 4701.59Skamil 4711.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 4721.61Skre SYSCALL_REQUIRE( 4731.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 4741.59Skamil 4751.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 4761.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 4771.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 4781.61Skre info.psi_siginfo.si_errno); 4791.59Skamil 4801.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 4811.59Skamil switch (sig) { 4821.59Skamil case SIGTRAP: 4831.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 4841.59Skamil break; 4851.59Skamil case SIGSEGV: 4861.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 4871.59Skamil break; 4881.71Skamil case SIGILL: 4891.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 4901.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 4911.71Skamil break; 4921.59Skamil case SIGFPE: 4931.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 4941.59Skamil break; 4951.59Skamil case SIGBUS: 4961.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 4971.59Skamil break; 4981.59Skamil } 4991.59Skamil 5001.59Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 5011.59Skamil 5021.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5031.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 5041.59Skamil 5051.59Skamil validate_status_signaled(status, SIGKILL, 0); 5061.59Skamil 5071.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5081.59Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 5091.59Skamil} 5101.59Skamil 5111.61Skre#define TRACEME_CRASH(test, sig) \ 5121.61SkreATF_TC(test); \ 5131.61SkreATF_TC_HEAD(test, tc) \ 5141.61Skre{ \ 5151.61Skre atf_tc_set_md_var(tc, "descr", \ 5161.61Skre "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \ 5171.61Skre} \ 5181.61Skre \ 5191.61SkreATF_TC_BODY(test, tc) \ 5201.61Skre{ \ 5211.61Skre \ 5221.61Skre traceme_crash(sig); \ 5231.59Skamil} 5241.59Skamil 5251.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP) 5261.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV) 5271.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL) 5281.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE) 5291.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS) 5301.59Skamil 5311.59Skamil/// ---------------------------------------------------------------------------- 5321.59Skamil 5331.59Skamilstatic void 5341.88Skamiltraceme_signalmasked_crash(int sig) 5351.88Skamil{ 5361.89Skamil const int sigval = SIGSTOP; 5371.88Skamil pid_t child, wpid; 5381.88Skamil#if defined(TWAIT_HAVE_STATUS) 5391.88Skamil int status; 5401.88Skamil#endif 5411.88Skamil struct ptrace_siginfo info; 5421.88Skamil sigset_t intmask; 5431.89Skamil struct kinfo_proc2 kp; 5441.89Skamil size_t len = sizeof(kp); 5451.89Skamil 5461.89Skamil int name[6]; 5471.89Skamil const size_t namelen = __arraycount(name); 5481.89Skamil ki_sigset_t kp_sigmask; 5491.88Skamil 5501.88Skamil#ifndef PTRACE_ILLEGAL_ASM 5511.88Skamil if (sig == SIGILL) 5521.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 5531.88Skamil#endif 5541.88Skamil 5551.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 5561.114Skamil atf_tc_skip("FP exceptions are not supported"); 5571.114Skamil 5581.88Skamil memset(&info, 0, sizeof(info)); 5591.88Skamil 5601.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 5611.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 5621.88Skamil if (child == 0) { 5631.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 5641.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 5651.88Skamil 5661.88Skamil sigemptyset(&intmask); 5671.88Skamil sigaddset(&intmask, sig); 5681.88Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 5691.88Skamil 5701.89Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 5711.89Skamil FORKEE_ASSERT(raise(sigval) == 0); 5721.89Skamil 5731.88Skamil DPRINTF("Before executing a trap\n"); 5741.88Skamil switch (sig) { 5751.88Skamil case SIGTRAP: 5761.88Skamil trigger_trap(); 5771.88Skamil break; 5781.88Skamil case SIGSEGV: 5791.88Skamil trigger_segv(); 5801.88Skamil break; 5811.88Skamil case SIGILL: 5821.88Skamil trigger_ill(); 5831.88Skamil break; 5841.88Skamil case SIGFPE: 5851.88Skamil trigger_fpe(); 5861.88Skamil break; 5871.88Skamil case SIGBUS: 5881.88Skamil trigger_bus(); 5891.88Skamil break; 5901.88Skamil default: 5911.88Skamil /* NOTREACHED */ 5921.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 5931.88Skamil } 5941.88Skamil 5951.88Skamil /* NOTREACHED */ 5961.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 5971.88Skamil } 5981.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 5991.88Skamil 6001.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6011.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6021.88Skamil 6031.89Skamil validate_status_stopped(status, sigval); 6041.89Skamil 6051.89Skamil name[0] = CTL_KERN, 6061.89Skamil name[1] = KERN_PROC2, 6071.89Skamil name[2] = KERN_PROC_PID; 6081.89Skamil name[3] = child; 6091.89Skamil name[4] = sizeof(kp); 6101.89Skamil name[5] = 1; 6111.89Skamil 6121.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6131.89Skamil 6141.89Skamil kp_sigmask = kp.p_sigmask; 6151.89Skamil 6161.89Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 6171.89Skamil SYSCALL_REQUIRE( 6181.89Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6191.89Skamil 6201.89Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6211.89Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6221.89Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6231.89Skamil info.psi_siginfo.si_errno); 6241.89Skamil 6251.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 6261.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 6271.89Skamil 6281.89Skamil DPRINTF("Before resuming the child process where it left off and " 6291.89Skamil "without signal to be sent\n"); 6301.89Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 6311.89Skamil 6321.89Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6331.89Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6341.89Skamil 6351.88Skamil validate_status_stopped(status, sig); 6361.88Skamil 6371.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 6381.88Skamil SYSCALL_REQUIRE( 6391.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6401.88Skamil 6411.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6421.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6431.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6441.88Skamil info.psi_siginfo.si_errno); 6451.88Skamil 6461.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6471.89Skamil 6481.89Skamil DPRINTF("kp_sigmask=" 6491.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6501.89Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2], 6511.89Skamil kp_sigmask.__bits[3]); 6521.89Skamil 6531.89Skamil DPRINTF("kp.p_sigmask=" 6541.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6551.89Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 6561.89Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 6571.89Skamil 6581.89Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask))); 6591.89Skamil 6601.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 6611.88Skamil switch (sig) { 6621.88Skamil case SIGTRAP: 6631.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 6641.88Skamil break; 6651.88Skamil case SIGSEGV: 6661.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 6671.88Skamil break; 6681.88Skamil case SIGILL: 6691.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 6701.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 6711.88Skamil break; 6721.88Skamil case SIGFPE: 6731.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 6741.88Skamil break; 6751.88Skamil case SIGBUS: 6761.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 6771.88Skamil break; 6781.88Skamil } 6791.88Skamil 6801.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 6811.88Skamil 6821.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6831.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6841.88Skamil 6851.88Skamil validate_status_signaled(status, SIGKILL, 0); 6861.88Skamil 6871.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6881.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 6891.88Skamil} 6901.88Skamil 6911.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig) \ 6921.88SkamilATF_TC(test); \ 6931.88SkamilATF_TC_HEAD(test, tc) \ 6941.88Skamil{ \ 6951.88Skamil atf_tc_set_md_var(tc, "descr", \ 6961.88Skamil "Verify masked crash signal " #sig " in a child after " \ 6971.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 6981.88Skamil} \ 6991.88Skamil \ 7001.88SkamilATF_TC_BODY(test, tc) \ 7011.88Skamil{ \ 7021.88Skamil \ 7031.88Skamil traceme_signalmasked_crash(sig); \ 7041.88Skamil} 7051.88Skamil 7061.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP) 7071.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV) 7081.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL) 7091.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE) 7101.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS) 7111.88Skamil 7121.88Skamil/// ---------------------------------------------------------------------------- 7131.88Skamil 7141.88Skamilstatic void 7151.88Skamiltraceme_signalignored_crash(int sig) 7161.88Skamil{ 7171.90Skamil const int sigval = SIGSTOP; 7181.88Skamil pid_t child, wpid; 7191.88Skamil#if defined(TWAIT_HAVE_STATUS) 7201.88Skamil int status; 7211.88Skamil#endif 7221.88Skamil struct sigaction sa; 7231.88Skamil struct ptrace_siginfo info; 7241.90Skamil struct kinfo_proc2 kp; 7251.90Skamil size_t len = sizeof(kp); 7261.90Skamil 7271.90Skamil int name[6]; 7281.90Skamil const size_t namelen = __arraycount(name); 7291.90Skamil ki_sigset_t kp_sigignore; 7301.88Skamil 7311.88Skamil#ifndef PTRACE_ILLEGAL_ASM 7321.88Skamil if (sig == SIGILL) 7331.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 7341.88Skamil#endif 7351.88Skamil 7361.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 7371.114Skamil atf_tc_skip("FP exceptions are not supported"); 7381.114Skamil 7391.88Skamil memset(&info, 0, sizeof(info)); 7401.88Skamil 7411.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 7421.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 7431.88Skamil if (child == 0) { 7441.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 7451.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 7461.88Skamil 7471.88Skamil memset(&sa, 0, sizeof(sa)); 7481.88Skamil sa.sa_handler = SIG_IGN; 7491.88Skamil sigemptyset(&sa.sa_mask); 7501.88Skamil 7511.88Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 7521.88Skamil 7531.90Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 7541.90Skamil FORKEE_ASSERT(raise(sigval) == 0); 7551.90Skamil 7561.88Skamil DPRINTF("Before executing a trap\n"); 7571.88Skamil switch (sig) { 7581.88Skamil case SIGTRAP: 7591.88Skamil trigger_trap(); 7601.88Skamil break; 7611.88Skamil case SIGSEGV: 7621.88Skamil trigger_segv(); 7631.88Skamil break; 7641.88Skamil case SIGILL: 7651.88Skamil trigger_ill(); 7661.88Skamil break; 7671.88Skamil case SIGFPE: 7681.88Skamil trigger_fpe(); 7691.88Skamil break; 7701.88Skamil case SIGBUS: 7711.88Skamil trigger_bus(); 7721.88Skamil break; 7731.88Skamil default: 7741.88Skamil /* NOTREACHED */ 7751.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7761.88Skamil } 7771.88Skamil 7781.88Skamil /* NOTREACHED */ 7791.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7801.88Skamil } 7811.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 7821.88Skamil 7831.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7841.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 7851.88Skamil 7861.90Skamil validate_status_stopped(status, sigval); 7871.90Skamil 7881.90Skamil name[0] = CTL_KERN, 7891.90Skamil name[1] = KERN_PROC2, 7901.90Skamil name[2] = KERN_PROC_PID; 7911.90Skamil name[3] = child; 7921.90Skamil name[4] = sizeof(kp); 7931.90Skamil name[5] = 1; 7941.90Skamil 7951.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 7961.90Skamil 7971.90Skamil kp_sigignore = kp.p_sigignore; 7981.90Skamil 7991.90Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 8001.90Skamil SYSCALL_REQUIRE( 8011.90Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8021.90Skamil 8031.90Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8041.90Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8051.90Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8061.90Skamil info.psi_siginfo.si_errno); 8071.90Skamil 8081.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 8091.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 8101.90Skamil 8111.90Skamil DPRINTF("Before resuming the child process where it left off and " 8121.90Skamil "without signal to be sent\n"); 8131.90Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 8141.90Skamil 8151.90Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8161.90Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8171.90Skamil 8181.88Skamil validate_status_stopped(status, sig); 8191.88Skamil 8201.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 8211.88Skamil SYSCALL_REQUIRE( 8221.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8231.88Skamil 8241.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8251.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8261.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8271.88Skamil info.psi_siginfo.si_errno); 8281.88Skamil 8291.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8301.90Skamil 8311.90Skamil DPRINTF("kp_sigignore=" 8321.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8331.90Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 8341.90Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 8351.90Skamil 8361.90Skamil DPRINTF("kp.p_sigignore=" 8371.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8381.90Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 8391.90Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 8401.90Skamil 8411.90Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore))); 8421.90Skamil 8431.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 8441.88Skamil switch (sig) { 8451.88Skamil case SIGTRAP: 8461.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 8471.88Skamil break; 8481.88Skamil case SIGSEGV: 8491.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 8501.88Skamil break; 8511.88Skamil case SIGILL: 8521.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 8531.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 8541.88Skamil break; 8551.88Skamil case SIGFPE: 8561.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 8571.88Skamil break; 8581.88Skamil case SIGBUS: 8591.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 8601.88Skamil break; 8611.88Skamil } 8621.88Skamil 8631.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 8641.88Skamil 8651.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8661.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8671.88Skamil 8681.88Skamil validate_status_signaled(status, SIGKILL, 0); 8691.88Skamil 8701.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8711.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 8721.88Skamil} 8731.88Skamil 8741.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig) \ 8751.88SkamilATF_TC(test); \ 8761.88SkamilATF_TC_HEAD(test, tc) \ 8771.88Skamil{ \ 8781.88Skamil atf_tc_set_md_var(tc, "descr", \ 8791.88Skamil "Verify ignored crash signal " #sig " in a child after " \ 8801.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 8811.88Skamil} \ 8821.88Skamil \ 8831.88SkamilATF_TC_BODY(test, tc) \ 8841.88Skamil{ \ 8851.88Skamil \ 8861.88Skamil traceme_signalignored_crash(sig); \ 8871.88Skamil} 8881.88Skamil 8891.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP) 8901.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV) 8911.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL) 8921.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE) 8931.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS) 8941.88Skamil 8951.88Skamil/// ---------------------------------------------------------------------------- 8961.88Skamil 8971.88Skamilstatic void 8981.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught) 8991.1Skamil{ 9001.1Skamil const int exitval = 5; 9011.34Skamil const int sigval = SIGSTOP; 9021.1Skamil pid_t child, wpid; 9031.1Skamil struct sigaction sa; 9041.1Skamil#if defined(TWAIT_HAVE_STATUS) 9051.1Skamil int status; 9061.1Skamil#endif 9071.61Skre struct ptrace_siginfo info; 9081.1Skamil 9091.45Skamil memset(&info, 0, sizeof(info)); 9101.45Skamil 9111.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 9121.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 9131.1Skamil if (child == 0) { 9141.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 9151.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 9161.1Skamil 9171.34Skamil sa.sa_handler = sah; 9181.1Skamil sa.sa_flags = SA_SIGINFO; 9191.1Skamil sigemptyset(&sa.sa_mask); 9201.1Skamil 9211.1Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 9221.1Skamil 9231.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 9241.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 9251.1Skamil 9261.34Skamil FORKEE_ASSERT_EQ(*traceme_caught, 1); 9271.1Skamil 9281.13Schristos DPRINTF("Before exiting of the child process\n"); 9291.1Skamil _exit(exitval); 9301.1Skamil } 9311.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 9321.1Skamil 9331.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9341.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9351.1Skamil 9361.1Skamil validate_status_stopped(status, sigval); 9371.1Skamil 9381.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 9391.61Skre SYSCALL_REQUIRE( 9401.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 9411.45Skamil 9421.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 9431.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 9441.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 9451.45Skamil info.psi_siginfo.si_errno); 9461.45Skamil 9471.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 9481.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 9491.45Skamil 9501.13Schristos DPRINTF("Before resuming the child process where it left off and with " 9511.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 9521.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 9531.1Skamil 9541.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9551.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9561.1Skamil 9571.1Skamil validate_status_exited(status, exitval); 9581.1Skamil 9591.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 9601.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 9611.1Skamil} 9621.1Skamil 9631.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig) \ 9641.61SkreATF_TC(test); \ 9651.61SkreATF_TC_HEAD(test, tc) \ 9661.61Skre{ \ 9671.61Skre atf_tc_set_md_var(tc, "descr", \ 9681.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 9691.61Skre "handled correctly and caught by a signal handler"); \ 9701.61Skre} \ 9711.61Skre \ 9721.61Skrestatic int test##_caught = 0; \ 9731.61Skre \ 9741.61Skrestatic void \ 9751.61Skretest##_sighandler(int arg) \ 9761.61Skre{ \ 9771.61Skre FORKEE_ASSERT_EQ(arg, sig); \ 9781.61Skre \ 9791.61Skre ++ test##_caught; \ 9801.61Skre} \ 9811.61Skre \ 9821.61SkreATF_TC_BODY(test, tc) \ 9831.61Skre{ \ 9841.61Skre \ 9851.61Skre traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \ 9861.34Skamil} 9871.34Skamil 9881.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered. 9891.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */ 9901.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP) /* hangup */ 9911.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */ 9921.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */ 9931.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */ 9941.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */ 9951.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */ 9961.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */ 9971.34Skamil 9981.34Skamil/// ---------------------------------------------------------------------------- 9991.34Skamil 10001.35Skamilstatic void 10011.50Skamiltraceme_sendsignal_masked(int sigsent) 10021.50Skamil{ 10031.50Skamil const int exitval = 5; 10041.50Skamil const int sigval = SIGSTOP; 10051.50Skamil pid_t child, wpid; 10061.50Skamil sigset_t set; 10071.50Skamil#if defined(TWAIT_HAVE_STATUS) 10081.50Skamil int status; 10091.50Skamil#endif 10101.61Skre struct ptrace_siginfo info; 10111.50Skamil 10121.50Skamil memset(&info, 0, sizeof(info)); 10131.50Skamil 10141.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 10151.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 10161.50Skamil if (child == 0) { 10171.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 10181.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 10191.50Skamil 10201.50Skamil sigemptyset(&set); 10211.50Skamil sigaddset(&set, sigsent); 10221.50Skamil FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 10231.50Skamil 10241.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 10251.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 10261.50Skamil 10271.50Skamil _exit(exitval); 10281.50Skamil } 10291.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 10301.50Skamil 10311.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10321.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10331.50Skamil 10341.50Skamil validate_status_stopped(status, sigval); 10351.50Skamil 10361.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 10371.61Skre SYSCALL_REQUIRE( 10381.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 10391.50Skamil 10401.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 10411.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 10421.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 10431.50Skamil info.psi_siginfo.si_errno); 10441.50Skamil 10451.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 10461.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 10471.50Skamil 10481.50Skamil DPRINTF("Before resuming the child process where it left off and with " 10491.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 10501.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 10511.50Skamil 10521.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10531.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10541.50Skamil 10551.50Skamil validate_status_exited(status, exitval); 10561.50Skamil 10571.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 10581.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 10591.50Skamil} 10601.50Skamil 10611.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig) \ 10621.61SkreATF_TC(test); \ 10631.61SkreATF_TC_HEAD(test, tc) \ 10641.61Skre{ \ 10651.61Skre atf_tc_set_md_var(tc, "descr", \ 10661.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 10671.61Skre "handled correctly and the signal is masked by SIG_BLOCK"); \ 10681.61Skre} \ 10691.61Skre \ 10701.61SkreATF_TC_BODY(test, tc) \ 10711.61Skre{ \ 10721.61Skre \ 10731.61Skre traceme_sendsignal_masked(sig); \ 10741.50Skamil} 10751.50Skamil 10761.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 10771.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */ 10781.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP) /* hangup */ 10791.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */ 10801.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */ 10811.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */ 10821.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */ 10831.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */ 10841.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */ 10851.50Skamil 10861.50Skamil/// ---------------------------------------------------------------------------- 10871.50Skamil 10881.50Skamilstatic void 10891.50Skamiltraceme_sendsignal_ignored(int sigsent) 10901.50Skamil{ 10911.50Skamil const int exitval = 5; 10921.50Skamil const int sigval = SIGSTOP; 10931.50Skamil pid_t child, wpid; 10941.50Skamil struct sigaction sa; 10951.50Skamil#if defined(TWAIT_HAVE_STATUS) 10961.50Skamil int status; 10971.50Skamil#endif 10981.61Skre struct ptrace_siginfo info; 10991.50Skamil 11001.50Skamil memset(&info, 0, sizeof(info)); 11011.50Skamil 11021.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 11031.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 11041.50Skamil if (child == 0) { 11051.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 11061.61Skre 11071.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 11081.50Skamil 11091.50Skamil memset(&sa, 0, sizeof(sa)); 11101.50Skamil sa.sa_handler = SIG_IGN; 11111.50Skamil sigemptyset(&sa.sa_mask); 11121.50Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 11131.50Skamil 11141.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 11151.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 11161.50Skamil 11171.50Skamil _exit(exitval); 11181.50Skamil } 11191.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 11201.50Skamil 11211.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11221.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11231.50Skamil 11241.50Skamil validate_status_stopped(status, sigval); 11251.50Skamil 11261.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 11271.61Skre SYSCALL_REQUIRE( 11281.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 11291.50Skamil 11301.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 11311.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 11321.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 11331.50Skamil info.psi_siginfo.si_errno); 11341.50Skamil 11351.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 11361.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 11371.50Skamil 11381.50Skamil DPRINTF("Before resuming the child process where it left off and with " 11391.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 11401.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 11411.50Skamil 11421.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11431.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11441.50Skamil 11451.50Skamil validate_status_exited(status, exitval); 11461.50Skamil 11471.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 11481.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 11491.50Skamil} 11501.50Skamil 11511.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig) \ 11521.61SkreATF_TC(test); \ 11531.61SkreATF_TC_HEAD(test, tc) \ 11541.61Skre{ \ 11551.61Skre atf_tc_set_md_var(tc, "descr", \ 11561.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 11571.61Skre "handled correctly and the signal is masked by SIG_IGN"); \ 11581.61Skre} \ 11591.61Skre \ 11601.61SkreATF_TC_BODY(test, tc) \ 11611.61Skre{ \ 11621.61Skre \ 11631.61Skre traceme_sendsignal_ignored(sig); \ 11641.50Skamil} 11651.50Skamil 11661.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 11671.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */ 11681.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP) /* hangup */ 11691.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */ 11701.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */ 11711.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */ 11721.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */ 11731.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */ 11741.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */ 11751.50Skamil 11761.50Skamil/// ---------------------------------------------------------------------------- 11771.50Skamil 11781.50Skamilstatic void 11791.50Skamiltraceme_sendsignal_simple(int sigsent) 11801.1Skamil{ 11811.35Skamil const int sigval = SIGSTOP; 11821.35Skamil int exitval = 0; 11831.1Skamil pid_t child, wpid; 11841.1Skamil#if defined(TWAIT_HAVE_STATUS) 11851.1Skamil int status; 11861.85Skamil int expect_core; 11871.85Skamil 11881.85Skamil switch (sigsent) { 11891.85Skamil case SIGABRT: 11901.85Skamil case SIGTRAP: 11911.85Skamil case SIGBUS: 11921.85Skamil case SIGILL: 11931.85Skamil case SIGFPE: 11941.85Skamil case SIGSEGV: 11951.85Skamil expect_core = 1; 11961.85Skamil break; 11971.85Skamil default: 11981.85Skamil expect_core = 0; 11991.85Skamil break; 12001.85Skamil } 12011.1Skamil#endif 12021.61Skre struct ptrace_siginfo info; 12031.1Skamil 12041.45Skamil memset(&info, 0, sizeof(info)); 12051.45Skamil 12061.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 12071.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 12081.1Skamil if (child == 0) { 12091.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 12101.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 12111.1Skamil 12121.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 12131.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 12141.1Skamil 12151.35Skamil switch (sigsent) { 12161.35Skamil case SIGCONT: 12171.48Skamil case SIGSTOP: 12181.35Skamil _exit(exitval); 12191.35Skamil default: 12201.35Skamil /* NOTREACHED */ 12211.35Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 12221.35Skamil } 12231.1Skamil } 12241.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 12251.1Skamil 12261.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12271.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12281.1Skamil 12291.1Skamil validate_status_stopped(status, sigval); 12301.1Skamil 12311.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 12321.61Skre SYSCALL_REQUIRE( 12331.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 12341.45Skamil 12351.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12361.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 12371.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12381.45Skamil info.psi_siginfo.si_errno); 12391.45Skamil 12401.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12411.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12421.45Skamil 12431.13Schristos DPRINTF("Before resuming the child process where it left off and with " 12441.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 12451.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 12461.1Skamil 12471.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12481.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12491.1Skamil 12501.35Skamil switch (sigsent) { 12511.48Skamil case SIGSTOP: 12521.48Skamil validate_status_stopped(status, sigsent); 12531.48Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 12541.61Skre "child\n"); 12551.48Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 12561.61Skre sizeof(info)) != -1); 12571.48Skamil 12581.48Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12591.48Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 12601.61Skre "si_errno=%#x\n", 12611.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12621.61Skre info.psi_siginfo.si_errno); 12631.48Skamil 12641.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12651.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12661.48Skamil 12671.48Skamil DPRINTF("Before resuming the child process where it left off " 12681.61Skre "and with signal %s to be sent\n", strsignal(sigsent)); 12691.48Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 12701.48Skamil 12711.48Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12721.48Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 12731.61Skre child); 12741.48Skamil /* FALLTHROUGH */ 12751.35Skamil case SIGCONT: 12761.35Skamil validate_status_exited(status, exitval); 12771.35Skamil break; 12781.35Skamil default: 12791.35Skamil validate_status_signaled(status, sigsent, expect_core); 12801.35Skamil break; 12811.35Skamil } 12821.1Skamil 12831.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 12841.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 12851.1Skamil} 12861.1Skamil 12871.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig) \ 12881.61SkreATF_TC(test); \ 12891.61SkreATF_TC_HEAD(test, tc) \ 12901.61Skre{ \ 12911.61Skre atf_tc_set_md_var(tc, "descr", \ 12921.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 12931.61Skre "handled correctly in a child without a signal handler"); \ 12941.61Skre} \ 12951.61Skre \ 12961.61SkreATF_TC_BODY(test, tc) \ 12971.61Skre{ \ 12981.61Skre \ 12991.61Skre traceme_sendsignal_simple(sig); \ 13001.35Skamil} 13011.35Skamil 13021.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/ 13031.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/ 13041.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */ 13051.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP) /* hangup */ 13061.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */ 13071.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */ 13081.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */ 13091.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */ 13101.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */ 13111.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */ 13121.35Skamil 13131.35Skamil/// ---------------------------------------------------------------------------- 13141.35Skamil 13151.37SkamilATF_TC(traceme_pid1_parent); 13161.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc) 13171.37Skamil{ 13181.37Skamil atf_tc_set_md_var(tc, "descr", 13191.37Skamil "Verify that PT_TRACE_ME is not allowed when our parent is PID1"); 13201.37Skamil} 13211.37Skamil 13221.37SkamilATF_TC_BODY(traceme_pid1_parent, tc) 13231.37Skamil{ 13241.37Skamil struct msg_fds parent_child; 13251.37Skamil int exitval_child1 = 1, exitval_child2 = 2; 13261.37Skamil pid_t child1, child2, wpid; 13271.37Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 13281.37Skamil#if defined(TWAIT_HAVE_STATUS) 13291.37Skamil int status; 13301.37Skamil#endif 13311.37Skamil 13321.37Skamil SYSCALL_REQUIRE(msg_open(&parent_child) == 0); 13331.37Skamil 13341.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13351.37Skamil SYSCALL_REQUIRE((child1 = fork()) != -1); 13361.37Skamil if (child1 == 0) { 13371.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13381.37Skamil SYSCALL_REQUIRE((child2 = fork()) != -1); 13391.37Skamil if (child2 != 0) { 13401.37Skamil DPRINTF("Parent process PID=%d, child2's PID=%d\n", 13411.61Skre getpid(), child2); 13421.37Skamil _exit(exitval_child1); 13431.37Skamil } 13441.37Skamil CHILD_FROM_PARENT("exit child1", parent_child, msg); 13451.37Skamil 13461.37Skamil DPRINTF("Assert that our parent is PID1 (initproc)\n"); 13471.37Skamil FORKEE_ASSERT_EQ(getppid(), 1); 13481.37Skamil 13491.37Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 13501.37Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1); 13511.37Skamil SYSCALL_REQUIRE_ERRNO(errno, EPERM); 13521.37Skamil 13531.37Skamil CHILD_TO_PARENT("child2 exiting", parent_child, msg); 13541.37Skamil 13551.37Skamil _exit(exitval_child2); 13561.37Skamil } 13571.37Skamil DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1); 13581.37Skamil 13591.37Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 13601.61Skre TWAIT_REQUIRE_SUCCESS( 13611.61Skre wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1); 13621.37Skamil 13631.37Skamil validate_status_exited(status, exitval_child1); 13641.37Skamil 13651.37Skamil DPRINTF("Notify that child1 is dead\n"); 13661.37Skamil PARENT_TO_CHILD("exit child1", parent_child, msg); 13671.37Skamil 13681.37Skamil DPRINTF("Wait for exiting of child2\n"); 13691.37Skamil PARENT_FROM_CHILD("child2 exiting", parent_child, msg); 13701.37Skamil} 13711.37Skamil 13721.37Skamil/// ---------------------------------------------------------------------------- 13731.37Skamil 13741.40Skamilstatic void 13751.40Skamiltraceme_vfork_raise(int sigval) 13761.40Skamil{ 13771.46Skamil const int exitval = 5, exitval_watcher = 10; 13781.46Skamil pid_t child, parent, watcher, wpid; 13791.46Skamil int rv; 13801.40Skamil#if defined(TWAIT_HAVE_STATUS) 13811.40Skamil int status; 13821.85Skamil 13831.85Skamil /* volatile workarounds GCC -Werror=clobbered */ 13841.85Skamil volatile int expect_core; 13851.85Skamil 13861.85Skamil switch (sigval) { 13871.85Skamil case SIGABRT: 13881.85Skamil case SIGTRAP: 13891.85Skamil case SIGBUS: 13901.85Skamil case SIGILL: 13911.85Skamil case SIGFPE: 13921.85Skamil case SIGSEGV: 13931.85Skamil expect_core = 1; 13941.85Skamil break; 13951.85Skamil default: 13961.85Skamil expect_core = 0; 13971.85Skamil break; 13981.85Skamil } 13991.40Skamil#endif 14001.40Skamil 14011.46Skamil /* 14021.46Skamil * Spawn a dedicated thread to watch for a stopped child and emit 14031.46Skamil * the SIGKILL signal to it. 14041.46Skamil * 14051.46Skamil * vfork(2) might clobber watcher, this means that it's safer and 14061.46Skamil * simpler to reparent this process to initproc and forget about it. 14071.46Skamil */ 14081.46Skamil if (sigval == SIGSTOP) { 14091.46Skamil parent = getpid(); 14101.46Skamil 14111.46Skamil watcher = fork(); 14121.46Skamil ATF_REQUIRE(watcher != 1); 14131.46Skamil if (watcher == 0) { 14141.46Skamil /* Double fork(2) trick to reparent to initproc */ 14151.46Skamil watcher = fork(); 14161.46Skamil FORKEE_ASSERT_NEQ(watcher, -1); 14171.46Skamil if (watcher != 0) 14181.46Skamil _exit(exitval_watcher); 14191.46Skamil 14201.46Skamil child = await_stopped_child(parent); 14211.46Skamil 14221.46Skamil errno = 0; 14231.46Skamil rv = kill(child, SIGKILL); 14241.46Skamil FORKEE_ASSERT_EQ(rv, 0); 14251.46Skamil FORKEE_ASSERT_EQ(errno, 0); 14261.46Skamil 14271.46Skamil /* This exit value will be collected by initproc */ 14281.46Skamil _exit(0); 14291.46Skamil } 14301.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14311.46Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0), 14321.61Skre watcher); 14331.46Skamil 14341.46Skamil validate_status_exited(status, exitval_watcher); 14351.46Skamil 14361.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14371.61Skre TWAIT_REQUIRE_FAILURE(ECHILD, 14381.61Skre wpid = TWAIT_GENERIC(watcher, &status, 0)); 14391.46Skamil } 14401.46Skamil 14411.40Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 14421.40Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 14431.40Skamil if (child == 0) { 14441.40Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 14451.40Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 14461.40Skamil 14471.40Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 14481.40Skamil FORKEE_ASSERT(raise(sigval) == 0); 14491.40Skamil 14501.40Skamil switch (sigval) { 14511.46Skamil case SIGSTOP: 14521.40Skamil case SIGKILL: 14531.40Skamil case SIGABRT: 14541.40Skamil case SIGHUP: 14551.85Skamil case SIGTRAP: 14561.85Skamil case SIGBUS: 14571.85Skamil case SIGILL: 14581.85Skamil case SIGFPE: 14591.85Skamil case SIGSEGV: 14601.40Skamil /* NOTREACHED */ 14611.40Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 14621.70Smrg __unreachable(); 14631.40Skamil default: 14641.40Skamil DPRINTF("Before exiting of the child process\n"); 14651.40Skamil _exit(exitval); 14661.40Skamil } 14671.40Skamil } 14681.40Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 14691.40Skamil 14701.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14711.40Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 14721.40Skamil 14731.40Skamil switch (sigval) { 14741.40Skamil case SIGKILL: 14751.40Skamil case SIGABRT: 14761.40Skamil case SIGHUP: 14771.85Skamil case SIGTRAP: 14781.85Skamil case SIGBUS: 14791.85Skamil case SIGILL: 14801.85Skamil case SIGFPE: 14811.85Skamil case SIGSEGV: 14821.40Skamil validate_status_signaled(status, sigval, expect_core); 14831.40Skamil break; 14841.40Skamil case SIGSTOP: 14851.46Skamil validate_status_signaled(status, SIGKILL, 0); 14861.46Skamil break; 14871.40Skamil case SIGCONT: 14881.47Skamil case SIGTSTP: 14891.47Skamil case SIGTTIN: 14901.47Skamil case SIGTTOU: 14911.40Skamil validate_status_exited(status, exitval); 14921.40Skamil break; 14931.40Skamil default: 14941.40Skamil /* NOTREACHED */ 14951.40Skamil ATF_REQUIRE(0 && "NOT IMPLEMENTED"); 14961.40Skamil break; 14971.40Skamil } 14981.40Skamil 14991.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15001.40Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15011.40Skamil} 15021.40Skamil 15031.61Skre#define TRACEME_VFORK_RAISE(test, sig) \ 15041.61SkreATF_TC(test); \ 15051.61SkreATF_TC_HEAD(test, tc) \ 15061.61Skre{ \ 15071.61Skre atf_tc_set_md_var(tc, "descr", \ 15081.61Skre "Verify PT_TRACE_ME followed by raise of " #sig " in a " \ 15091.61Skre "vfork(2)ed child"); \ 15101.61Skre} \ 15111.61Skre \ 15121.61SkreATF_TC_BODY(test, tc) \ 15131.61Skre{ \ 15141.61Skre \ 15151.61Skre traceme_vfork_raise(sig); \ 15161.40Skamil} 15171.40Skamil 15181.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */ 15191.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */ 15201.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */ 15211.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */ 15221.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */ 15231.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */ 15241.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP) /* hangup */ 15251.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */ 15261.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */ 15271.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */ 15281.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */ 15291.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */ 15301.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */ 15311.40Skamil 15321.40Skamil/// ---------------------------------------------------------------------------- 15331.40Skamil 15341.52Skamilstatic void 15351.52Skamiltraceme_vfork_crash(int sig) 15361.41Skamil{ 15371.41Skamil pid_t child, wpid; 15381.41Skamil#if defined(TWAIT_HAVE_STATUS) 15391.41Skamil int status; 15401.41Skamil#endif 15411.41Skamil 15421.71Skamil#ifndef PTRACE_ILLEGAL_ASM 15431.71Skamil if (sig == SIGILL) 15441.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 15451.71Skamil#endif 15461.71Skamil 15471.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 15481.114Skamil atf_tc_skip("FP exceptions are not supported"); 15491.114Skamil 15501.41Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 15511.41Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 15521.41Skamil if (child == 0) { 15531.41Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 15541.41Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 15551.41Skamil 15561.52Skamil DPRINTF("Before executing a trap\n"); 15571.52Skamil switch (sig) { 15581.52Skamil case SIGTRAP: 15591.52Skamil trigger_trap(); 15601.52Skamil break; 15611.52Skamil case SIGSEGV: 15621.52Skamil trigger_segv(); 15631.52Skamil break; 15641.52Skamil case SIGILL: 15651.52Skamil trigger_ill(); 15661.52Skamil break; 15671.52Skamil case SIGFPE: 15681.52Skamil trigger_fpe(); 15691.52Skamil break; 15701.52Skamil case SIGBUS: 15711.52Skamil trigger_bus(); 15721.52Skamil break; 15731.52Skamil default: 15741.52Skamil /* NOTREACHED */ 15751.52Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15761.52Skamil } 15771.41Skamil 15781.41Skamil /* NOTREACHED */ 15791.41Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15801.41Skamil } 15811.41Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 15821.41Skamil 15831.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15841.41Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 15851.41Skamil 15861.52Skamil validate_status_signaled(status, sig, 1); 15871.41Skamil 15881.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15891.41Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15901.41Skamil} 15911.41Skamil 15921.61Skre#define TRACEME_VFORK_CRASH(test, sig) \ 15931.61SkreATF_TC(test); \ 15941.61SkreATF_TC_HEAD(test, tc) \ 15951.61Skre{ \ 15961.61Skre atf_tc_set_md_var(tc, "descr", \ 15971.61Skre "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 15981.61Skre "vfork(2)ed child"); \ 15991.61Skre} \ 16001.61Skre \ 16011.61SkreATF_TC_BODY(test, tc) \ 16021.61Skre{ \ 16031.61Skre \ 16041.61Skre traceme_vfork_crash(sig); \ 16051.52Skamil} 16061.52Skamil 16071.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP) 16081.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV) 16091.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL) 16101.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE) 16111.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS) 16121.52Skamil 16131.41Skamil/// ---------------------------------------------------------------------------- 16141.41Skamil 16151.92Skamilstatic void 16161.92Skamiltraceme_vfork_signalmasked_crash(int sig) 16171.92Skamil{ 16181.92Skamil pid_t child, wpid; 16191.92Skamil#if defined(TWAIT_HAVE_STATUS) 16201.92Skamil int status; 16211.92Skamil#endif 16221.92Skamil sigset_t intmask; 16231.92Skamil 16241.92Skamil#ifndef PTRACE_ILLEGAL_ASM 16251.92Skamil if (sig == SIGILL) 16261.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 16271.92Skamil#endif 16281.92Skamil 16291.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 16301.114Skamil atf_tc_skip("FP exceptions are not supported"); 16311.114Skamil 16321.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 16331.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 16341.92Skamil if (child == 0) { 16351.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 16361.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 16371.92Skamil 16381.92Skamil sigemptyset(&intmask); 16391.92Skamil sigaddset(&intmask, sig); 16401.92Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 16411.92Skamil 16421.92Skamil DPRINTF("Before executing a trap\n"); 16431.92Skamil switch (sig) { 16441.92Skamil case SIGTRAP: 16451.92Skamil trigger_trap(); 16461.92Skamil break; 16471.92Skamil case SIGSEGV: 16481.92Skamil trigger_segv(); 16491.92Skamil break; 16501.92Skamil case SIGILL: 16511.92Skamil trigger_ill(); 16521.92Skamil break; 16531.92Skamil case SIGFPE: 16541.92Skamil trigger_fpe(); 16551.92Skamil break; 16561.92Skamil case SIGBUS: 16571.92Skamil trigger_bus(); 16581.92Skamil break; 16591.92Skamil default: 16601.92Skamil /* NOTREACHED */ 16611.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16621.92Skamil } 16631.92Skamil 16641.92Skamil /* NOTREACHED */ 16651.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16661.92Skamil } 16671.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 16681.92Skamil 16691.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16701.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 16711.92Skamil 16721.92Skamil validate_status_signaled(status, sig, 1); 16731.92Skamil 16741.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16751.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 16761.92Skamil} 16771.92Skamil 16781.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig) \ 16791.92SkamilATF_TC(test); \ 16801.92SkamilATF_TC_HEAD(test, tc) \ 16811.92Skamil{ \ 16821.92Skamil atf_tc_set_md_var(tc, "descr", \ 16831.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16841.92Skamil "vfork(2)ed child with a masked signal"); \ 16851.92Skamil} \ 16861.92Skamil \ 16871.92SkamilATF_TC_BODY(test, tc) \ 16881.92Skamil{ \ 16891.92Skamil \ 16901.92Skamil traceme_vfork_signalmasked_crash(sig); \ 16911.92Skamil} 16921.92Skamil 16931.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP) 16941.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV) 16951.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL) 16961.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE) 16971.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS) 16981.92Skamil 16991.92Skamil/// ---------------------------------------------------------------------------- 17001.92Skamil 17011.92Skamilstatic void 17021.92Skamiltraceme_vfork_signalignored_crash(int sig) 17031.92Skamil{ 17041.92Skamil pid_t child, wpid; 17051.92Skamil#if defined(TWAIT_HAVE_STATUS) 17061.92Skamil int status; 17071.92Skamil#endif 17081.92Skamil struct sigaction sa; 17091.92Skamil 17101.92Skamil#ifndef PTRACE_ILLEGAL_ASM 17111.92Skamil if (sig == SIGILL) 17121.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 17131.92Skamil#endif 17141.92Skamil 17151.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 17161.114Skamil atf_tc_skip("FP exceptions are not supported"); 17171.114Skamil 17181.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 17191.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 17201.92Skamil if (child == 0) { 17211.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 17221.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 17231.92Skamil 17241.92Skamil memset(&sa, 0, sizeof(sa)); 17251.92Skamil sa.sa_handler = SIG_IGN; 17261.92Skamil sigemptyset(&sa.sa_mask); 17271.92Skamil 17281.92Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 17291.92Skamil 17301.92Skamil DPRINTF("Before executing a trap\n"); 17311.92Skamil switch (sig) { 17321.92Skamil case SIGTRAP: 17331.92Skamil trigger_trap(); 17341.92Skamil break; 17351.92Skamil case SIGSEGV: 17361.92Skamil trigger_segv(); 17371.92Skamil break; 17381.92Skamil case SIGILL: 17391.92Skamil trigger_ill(); 17401.92Skamil break; 17411.92Skamil case SIGFPE: 17421.92Skamil trigger_fpe(); 17431.92Skamil break; 17441.92Skamil case SIGBUS: 17451.92Skamil trigger_bus(); 17461.92Skamil break; 17471.92Skamil default: 17481.92Skamil /* NOTREACHED */ 17491.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17501.92Skamil } 17511.92Skamil 17521.92Skamil /* NOTREACHED */ 17531.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17541.92Skamil } 17551.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 17561.92Skamil 17571.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17581.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17591.92Skamil 17601.92Skamil validate_status_signaled(status, sig, 1); 17611.92Skamil 17621.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17631.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 17641.92Skamil} 17651.92Skamil 17661.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig) \ 17671.92SkamilATF_TC(test); \ 17681.92SkamilATF_TC_HEAD(test, tc) \ 17691.92Skamil{ \ 17701.92Skamil atf_tc_set_md_var(tc, "descr", \ 17711.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 17721.92Skamil "vfork(2)ed child with ignored signal"); \ 17731.92Skamil} \ 17741.92Skamil \ 17751.92SkamilATF_TC_BODY(test, tc) \ 17761.92Skamil{ \ 17771.92Skamil \ 17781.92Skamil traceme_vfork_signalignored_crash(sig); \ 17791.92Skamil} 17801.92Skamil 17811.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap, 17821.92Skamil SIGTRAP) 17831.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv, 17841.92Skamil SIGSEGV) 17851.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill, 17861.92Skamil SIGILL) 17871.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe, 17881.92Skamil SIGFPE) 17891.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus, 17901.92Skamil SIGBUS) 17911.92Skamil 17921.92Skamil/// ---------------------------------------------------------------------------- 17931.92Skamil 17941.96Skamilstatic void 17951.96Skamiltraceme_vfork_exec(bool masked, bool ignored) 17961.43Skamil{ 17971.43Skamil const int sigval = SIGTRAP; 17981.43Skamil pid_t child, wpid; 17991.43Skamil#if defined(TWAIT_HAVE_STATUS) 18001.43Skamil int status; 18011.43Skamil#endif 18021.96Skamil struct sigaction sa; 18031.61Skre struct ptrace_siginfo info; 18041.96Skamil sigset_t intmask; 18051.96Skamil struct kinfo_proc2 kp; 18061.96Skamil size_t len = sizeof(kp); 18071.96Skamil 18081.96Skamil int name[6]; 18091.96Skamil const size_t namelen = __arraycount(name); 18101.96Skamil ki_sigset_t kp_sigmask; 18111.96Skamil ki_sigset_t kp_sigignore; 18121.43Skamil 18131.43Skamil memset(&info, 0, sizeof(info)); 18141.43Skamil 18151.43Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 18161.43Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 18171.43Skamil if (child == 0) { 18181.43Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 18191.43Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 18201.43Skamil 18211.96Skamil if (masked) { 18221.96Skamil sigemptyset(&intmask); 18231.96Skamil sigaddset(&intmask, sigval); 18241.96Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 18251.96Skamil } 18261.96Skamil 18271.96Skamil if (ignored) { 18281.96Skamil memset(&sa, 0, sizeof(sa)); 18291.96Skamil sa.sa_handler = SIG_IGN; 18301.96Skamil sigemptyset(&sa.sa_mask); 18311.96Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 18321.96Skamil } 18331.96Skamil 18341.43Skamil DPRINTF("Before calling execve(2) from child\n"); 18351.43Skamil execlp("/bin/echo", "/bin/echo", NULL); 18361.43Skamil 18371.43Skamil /* NOTREACHED */ 18381.43Skamil FORKEE_ASSERTX(0 && "Not reached"); 18391.43Skamil } 18401.43Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 18411.43Skamil 18421.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 18431.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 18441.43Skamil 18451.43Skamil validate_status_stopped(status, sigval); 18461.43Skamil 18471.96Skamil name[0] = CTL_KERN, 18481.96Skamil name[1] = KERN_PROC2, 18491.96Skamil name[2] = KERN_PROC_PID; 18501.96Skamil name[3] = getpid(); 18511.96Skamil name[4] = sizeof(kp); 18521.96Skamil name[5] = 1; 18531.96Skamil 18541.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18551.96Skamil 18561.96Skamil if (masked) 18571.96Skamil kp_sigmask = kp.p_sigmask; 18581.96Skamil 18591.96Skamil if (ignored) 18601.96Skamil kp_sigignore = kp.p_sigignore; 18611.96Skamil 18621.96Skamil name[3] = getpid(); 18631.96Skamil 18641.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18651.96Skamil 18661.96Skamil if (masked) { 18671.96Skamil DPRINTF("kp_sigmask=" 18681.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18691.96Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 18701.96Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 18711.96Skamil 18721.96Skamil DPRINTF("kp.p_sigmask=" 18731.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18741.96Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 18751.96Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 18761.96Skamil 18771.96Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 18781.96Skamil sizeof(kp_sigmask))); 18791.96Skamil } 18801.96Skamil 18811.96Skamil if (ignored) { 18821.96Skamil DPRINTF("kp_sigignore=" 18831.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18841.96Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 18851.96Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 18861.96Skamil 18871.96Skamil DPRINTF("kp.p_sigignore=" 18881.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18891.96Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 18901.96Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 18911.96Skamil 18921.96Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 18931.96Skamil sizeof(kp_sigignore))); 18941.96Skamil } 18951.96Skamil 18961.43Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 18971.61Skre SYSCALL_REQUIRE( 18981.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 18991.43Skamil 19001.43Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 19011.43Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 19021.43Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 19031.43Skamil info.psi_siginfo.si_errno); 19041.43Skamil 19051.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 19061.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 19071.43Skamil 19081.43Skamil DPRINTF("Before resuming the child process where it left off and " 19091.43Skamil "without signal to be sent\n"); 19101.43Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 19111.43Skamil 19121.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19131.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 19141.43Skamil 19151.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19161.43Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 19171.43Skamil} 19181.43Skamil 19191.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored) \ 19201.96SkamilATF_TC(test); \ 19211.96SkamilATF_TC_HEAD(test, tc) \ 19221.96Skamil{ \ 19231.96Skamil atf_tc_set_md_var(tc, "descr", \ 19241.96Skamil "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed " \ 19251.96Skamil "child%s%s", masked ? " with masked signal" : "", \ 19261.96Skamil masked ? " with ignored signal" : ""); \ 19271.96Skamil} \ 19281.96Skamil \ 19291.96SkamilATF_TC_BODY(test, tc) \ 19301.96Skamil{ \ 19311.96Skamil \ 19321.96Skamil traceme_vfork_exec(masked, ignored); \ 19331.96Skamil} 19341.96Skamil 19351.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false) 19361.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false) 19371.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true) 19381.96Skamil 19391.43Skamil/// ---------------------------------------------------------------------------- 19401.43Skamil 19411.1Skamil#if defined(TWAIT_HAVE_PID) 19421.51Skamilstatic void 19431.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored) 19441.59Skamil{ 19451.94Skamil const int sigval = SIGSTOP; 19461.59Skamil struct msg_fds parent_tracee, parent_tracer; 19471.59Skamil const int exitval = 10; 19481.59Skamil pid_t tracee, tracer, wpid; 19491.59Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 19501.59Skamil#if defined(TWAIT_HAVE_STATUS) 19511.59Skamil int status; 19521.59Skamil#endif 19531.94Skamil struct sigaction sa; 19541.59Skamil struct ptrace_siginfo info; 19551.94Skamil sigset_t intmask; 19561.94Skamil struct kinfo_proc2 kp; 19571.94Skamil size_t len = sizeof(kp); 19581.94Skamil 19591.94Skamil int name[6]; 19601.94Skamil const size_t namelen = __arraycount(name); 19611.94Skamil ki_sigset_t kp_sigmask; 19621.94Skamil ki_sigset_t kp_sigignore; 19631.61Skre 19641.71Skamil#ifndef PTRACE_ILLEGAL_ASM 19651.71Skamil if (sig == SIGILL) 19661.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 19671.71Skamil#endif 19681.71Skamil 19691.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 19701.114Skamil atf_tc_skip("FP exceptions are not supported"); 19711.114Skamil 19721.59Skamil memset(&info, 0, sizeof(info)); 19731.59Skamil 19741.59Skamil DPRINTF("Spawn tracee\n"); 19751.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 19761.59Skamil tracee = atf_utils_fork(); 19771.59Skamil if (tracee == 0) { 19781.59Skamil // Wait for parent to let us crash 19791.59Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 19801.61Skre 19811.94Skamil if (masked) { 19821.94Skamil sigemptyset(&intmask); 19831.94Skamil sigaddset(&intmask, sig); 19841.94Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 19851.94Skamil } 19861.94Skamil 19871.94Skamil if (ignored) { 19881.94Skamil memset(&sa, 0, sizeof(sa)); 19891.94Skamil sa.sa_handler = SIG_IGN; 19901.94Skamil sigemptyset(&sa.sa_mask); 19911.94Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 19921.94Skamil } 19931.94Skamil 19941.94Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 19951.94Skamil FORKEE_ASSERT(raise(sigval) == 0); 19961.94Skamil 19971.59Skamil DPRINTF("Before executing a trap\n"); 19981.59Skamil switch (sig) { 19991.59Skamil case SIGTRAP: 20001.59Skamil trigger_trap(); 20011.59Skamil break; 20021.59Skamil case SIGSEGV: 20031.59Skamil trigger_segv(); 20041.59Skamil break; 20051.59Skamil case SIGILL: 20061.59Skamil trigger_ill(); 20071.59Skamil break; 20081.59Skamil case SIGFPE: 20091.59Skamil trigger_fpe(); 20101.59Skamil break; 20111.59Skamil case SIGBUS: 20121.59Skamil trigger_bus(); 20131.59Skamil break; 20141.59Skamil default: 20151.59Skamil /* NOTREACHED */ 20161.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20171.59Skamil } 20181.59Skamil 20191.59Skamil /* NOTREACHED */ 20201.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20211.59Skamil } 20221.59Skamil 20231.59Skamil DPRINTF("Spawn debugger\n"); 20241.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 20251.59Skamil tracer = atf_utils_fork(); 20261.59Skamil if (tracer == 0) { 20271.59Skamil /* Fork again and drop parent to reattach to PID 1 */ 20281.59Skamil tracer = atf_utils_fork(); 20291.59Skamil if (tracer != 0) 20301.61Skre _exit(exitval); 20311.59Skamil 20321.59Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 20331.59Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 20341.59Skamil 20351.59Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 20361.59Skamil FORKEE_REQUIRE_SUCCESS( 20371.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20381.59Skamil 20391.59Skamil forkee_status_stopped(status, SIGSTOP); 20401.59Skamil 20411.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20421.94Skamil "traced process\n"); 20431.94Skamil SYSCALL_REQUIRE( 20441.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20451.94Skamil 20461.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20471.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20481.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20491.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20501.94Skamil 20511.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 20521.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 20531.94Skamil 20541.59Skamil /* Resume tracee with PT_CONTINUE */ 20551.59Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 20561.59Skamil 20571.59Skamil /* Inform parent that tracer has attached to tracee */ 20581.59Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 20591.59Skamil 20601.59Skamil /* Wait for parent to tell use that tracee should have exited */ 20611.59Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 20621.59Skamil 20631.59Skamil /* Wait for tracee and assert that it exited */ 20641.59Skamil FORKEE_REQUIRE_SUCCESS( 20651.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20661.59Skamil 20671.94Skamil forkee_status_stopped(status, sigval); 20681.94Skamil 20691.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20701.94Skamil "traced process\n"); 20711.94Skamil SYSCALL_REQUIRE( 20721.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20731.94Skamil 20741.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20751.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20761.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20771.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20781.94Skamil 20791.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 20801.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 20811.94Skamil 20821.94Skamil name[0] = CTL_KERN, 20831.94Skamil name[1] = KERN_PROC2, 20841.94Skamil name[2] = KERN_PROC_PID; 20851.94Skamil name[3] = tracee; 20861.94Skamil name[4] = sizeof(kp); 20871.94Skamil name[5] = 1; 20881.94Skamil 20891.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 20901.94Skamil 20911.94Skamil if (masked) 20921.94Skamil kp_sigmask = kp.p_sigmask; 20931.94Skamil 20941.94Skamil if (ignored) 20951.94Skamil kp_sigignore = kp.p_sigignore; 20961.94Skamil 20971.94Skamil /* Resume tracee with PT_CONTINUE */ 20981.94Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 20991.94Skamil 21001.94Skamil /* Wait for tracee and assert that it exited */ 21011.94Skamil FORKEE_REQUIRE_SUCCESS( 21021.94Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21031.94Skamil 21041.93Skamil forkee_status_stopped(status, sig); 21051.59Skamil 21061.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 21071.61Skre "traced process\n"); 21081.61Skre SYSCALL_REQUIRE( 21091.61Skre ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 21101.59Skamil 21111.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21121.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21131.61Skre "si_errno=%#x\n", info.psi_siginfo.si_signo, 21141.61Skre info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 21151.59Skamil 21161.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig); 21171.94Skamil 21181.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21191.94Skamil 21201.94Skamil if (masked) { 21211.94Skamil DPRINTF("kp_sigmask=" 21221.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21231.94Skamil PRIx32 "\n", 21241.94Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 21251.94Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 21261.94Skamil 21271.94Skamil DPRINTF("kp.p_sigmask=" 21281.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21291.94Skamil PRIx32 "\n", 21301.94Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 21311.94Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 21321.94Skamil 21331.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask, 21341.94Skamil sizeof(kp_sigmask))); 21351.94Skamil } 21361.94Skamil 21371.94Skamil if (ignored) { 21381.94Skamil DPRINTF("kp_sigignore=" 21391.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21401.94Skamil PRIx32 "\n", 21411.94Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 21421.94Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 21431.94Skamil 21441.94Skamil DPRINTF("kp.p_sigignore=" 21451.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21461.94Skamil PRIx32 "\n", 21471.94Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 21481.94Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 21491.94Skamil 21501.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore, 21511.94Skamil sizeof(kp_sigignore))); 21521.94Skamil } 21531.94Skamil 21541.59Skamil switch (sig) { 21551.59Skamil case SIGTRAP: 21561.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 21571.59Skamil break; 21581.59Skamil case SIGSEGV: 21591.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 21601.59Skamil break; 21611.71Skamil case SIGILL: 21621.113Skamil FORKEE_ASSERT(info.psi_siginfo.si_code >= ILL_ILLOPC && 21631.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 21641.71Skamil break; 21651.59Skamil case SIGFPE: 21661.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 21671.59Skamil break; 21681.59Skamil case SIGBUS: 21691.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 21701.59Skamil break; 21711.59Skamil } 21721.59Skamil 21731.59Skamil FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1); 21741.59Skamil DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME); 21751.93Skamil FORKEE_REQUIRE_SUCCESS( 21761.61Skre wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21771.59Skamil 21781.93Skamil forkee_status_signaled(status, SIGKILL, 0); 21791.59Skamil 21801.71Skamil /* Inform parent that tracer is exiting normally */ 21811.71Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 21821.71Skamil 21831.59Skamil DPRINTF("Before exiting of the tracer process\n"); 21841.59Skamil _exit(0 /* collect by initproc */); 21851.59Skamil } 21861.59Skamil 21871.59Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 21881.59Skamil "calling %s()\n", TWAIT_FNAME); 21891.59Skamil TWAIT_REQUIRE_SUCCESS( 21901.59Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 21911.59Skamil 21921.59Skamil validate_status_exited(status, exitval); 21931.59Skamil 21941.59Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 21951.59Skamil TWAIT_FNAME); 21961.59Skamil TWAIT_REQUIRE_SUCCESS( 21971.59Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 21981.59Skamil 21991.59Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 22001.59Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 22011.59Skamil 22021.59Skamil DPRINTF("Resume the tracee and let it crash\n"); 22031.59Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 22041.59Skamil 22051.59Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 22061.59Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 22071.59Skamil 22081.59Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 22091.59Skamil TWAIT_FNAME); 22101.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22111.59Skamil 22121.59Skamil validate_status_signaled(status, SIGKILL, 0); 22131.59Skamil 22141.71Skamil DPRINTF("Await normal exit of tracer\n"); 22151.71Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 22161.71Skamil 22171.59Skamil msg_close(&parent_tracer); 22181.59Skamil msg_close(&parent_tracee); 22191.59Skamil} 22201.59Skamil 22211.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig) \ 22221.61SkreATF_TC(test); \ 22231.61SkreATF_TC_HEAD(test, tc) \ 22241.61Skre{ \ 22251.61Skre atf_tc_set_md_var(tc, "descr", \ 22261.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22271.94Skamil "the debuggee"); \ 22281.61Skre} \ 22291.61Skre \ 22301.61SkreATF_TC_BODY(test, tc) \ 22311.61Skre{ \ 22321.61Skre \ 22331.94Skamil unrelated_tracer_sees_crash(sig, false, false); \ 22341.59Skamil} 22351.59Skamil 22361.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP) 22371.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV) 22381.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL) 22391.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE) 22401.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS) 22411.94Skamil 22421.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig) \ 22431.94SkamilATF_TC(test); \ 22441.94SkamilATF_TC_HEAD(test, tc) \ 22451.94Skamil{ \ 22461.94Skamil atf_tc_set_md_var(tc, "descr", \ 22471.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22481.94Skamil "the debuggee with masked signal"); \ 22491.94Skamil} \ 22501.94Skamil \ 22511.94SkamilATF_TC_BODY(test, tc) \ 22521.94Skamil{ \ 22531.94Skamil \ 22541.94Skamil unrelated_tracer_sees_crash(sig, true, false); \ 22551.94Skamil} 22561.94Skamil 22571.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22581.94Skamil unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP) 22591.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22601.94Skamil unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV) 22611.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22621.94Skamil unrelated_tracer_sees_signalmasked_crash_ill, SIGILL) 22631.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22641.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE) 22651.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22661.94Skamil unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS) 22671.94Skamil 22681.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_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 signal ignored"); \ 22751.94Skamil} \ 22761.94Skamil \ 22771.94SkamilATF_TC_BODY(test, tc) \ 22781.94Skamil{ \ 22791.94Skamil \ 22801.94Skamil unrelated_tracer_sees_crash(sig, false, true); \ 22811.94Skamil} 22821.94Skamil 22831.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22841.94Skamil unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP) 22851.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22861.94Skamil unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV) 22871.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22881.94Skamil unrelated_tracer_sees_signalignored_crash_ill, SIGILL) 22891.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22901.94Skamil unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE) 22911.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22921.94Skamil unrelated_tracer_sees_signalignored_crash_bus, SIGBUS) 22931.59Skamil#endif 22941.59Skamil 22951.59Skamil/// ---------------------------------------------------------------------------- 22961.59Skamil 22971.59Skamil#if defined(TWAIT_HAVE_PID) 22981.59Skamilstatic void 22991.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated, 23001.67Skamil bool stopped) 23011.1Skamil{ 23021.51Skamil /* 23031.51Skamil * notimeout - disable timeout in await zombie function 23041.51Skamil * unrelated - attach from unrelated tracer reparented to initproc 23051.67Skamil * stopped - attach to a stopped process 23061.51Skamil */ 23071.1Skamil 23081.1Skamil struct msg_fds parent_tracee, parent_tracer; 23091.1Skamil const int exitval_tracee = 5; 23101.1Skamil const int exitval_tracer = 10; 23111.1Skamil pid_t tracee, tracer, wpid; 23121.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 23131.1Skamil#if defined(TWAIT_HAVE_STATUS) 23141.1Skamil int status; 23151.1Skamil#endif 23161.1Skamil 23171.67Skamil /* 23181.67Skamil * Only a subset of options are supported. 23191.67Skamil */ 23201.67Skamil ATF_REQUIRE((!notimeout && !unrelated && !stopped) || 23211.67Skamil (!notimeout && unrelated && !stopped) || 23221.67Skamil (notimeout && !unrelated && !stopped) || 23231.67Skamil (!notimeout && unrelated && stopped)); 23241.67Skamil 23251.13Schristos DPRINTF("Spawn tracee\n"); 23261.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 23271.1Skamil tracee = atf_utils_fork(); 23281.1Skamil if (tracee == 0) { 23291.67Skamil if (stopped) { 23301.67Skamil DPRINTF("Stop self PID %d\n", getpid()); 23311.67Skamil raise(SIGSTOP); 23321.67Skamil } 23331.67Skamil 23341.1Skamil // Wait for parent to let us exit 23351.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 23361.1Skamil _exit(exitval_tracee); 23371.1Skamil } 23381.1Skamil 23391.13Schristos DPRINTF("Spawn debugger\n"); 23401.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 23411.1Skamil tracer = atf_utils_fork(); 23421.1Skamil if (tracer == 0) { 23431.51Skamil if(unrelated) { 23441.51Skamil /* Fork again and drop parent to reattach to PID 1 */ 23451.51Skamil tracer = atf_utils_fork(); 23461.51Skamil if (tracer != 0) 23471.51Skamil _exit(exitval_tracer); 23481.51Skamil } 23491.51Skamil 23501.67Skamil if (stopped) { 23511.67Skamil DPRINTF("Await for a stopped parent PID %d\n", tracee); 23521.67Skamil await_stopped(tracee); 23531.67Skamil } 23541.67Skamil 23551.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 23561.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 23571.1Skamil 23581.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 23591.1Skamil FORKEE_REQUIRE_SUCCESS( 23601.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23611.1Skamil 23621.1Skamil forkee_status_stopped(status, SIGSTOP); 23631.1Skamil 23641.1Skamil /* Resume tracee with PT_CONTINUE */ 23651.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 23661.1Skamil 23671.1Skamil /* Inform parent that tracer has attached to tracee */ 23681.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 23691.1Skamil 23701.1Skamil /* Wait for parent to tell use that tracee should have exited */ 23711.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 23721.1Skamil 23731.1Skamil /* Wait for tracee and assert that it exited */ 23741.1Skamil FORKEE_REQUIRE_SUCCESS( 23751.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23761.1Skamil 23771.1Skamil forkee_status_exited(status, exitval_tracee); 23781.13Schristos DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee); 23791.1Skamil 23801.13Schristos DPRINTF("Before exiting of the tracer process\n"); 23811.51Skamil _exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer); 23821.51Skamil } 23831.51Skamil 23841.51Skamil if (unrelated) { 23851.51Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 23861.51Skamil "calling %s()\n", TWAIT_FNAME); 23871.51Skamil TWAIT_REQUIRE_SUCCESS( 23881.51Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 23891.51Skamil 23901.51Skamil validate_status_exited(status, exitval_tracer); 23911.51Skamil 23921.51Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 23931.51Skamil TWAIT_FNAME); 23941.51Skamil TWAIT_REQUIRE_SUCCESS( 23951.51Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 23961.1Skamil } 23971.1Skamil 23981.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 23991.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 24001.1Skamil 24011.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 24021.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 24031.1Skamil 24041.13Schristos DPRINTF("Detect that tracee is zombie\n"); 24051.51Skamil if (notimeout) 24061.26Skamil await_zombie_raw(tracee, 0); 24071.26Skamil else 24081.26Skamil await_zombie(tracee); 24091.1Skamil 24101.13Schristos DPRINTF("Assert that there is no status about tracee %d - " 24111.1Skamil "Tracer must detect zombie first - calling %s()\n", tracee, 24121.1Skamil TWAIT_FNAME); 24131.1Skamil TWAIT_REQUIRE_SUCCESS( 24141.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 24151.1Skamil 24161.51Skamil if (unrelated) { 24171.51Skamil DPRINTF("Resume the tracer and let it detect exited tracee\n"); 24181.51Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 24191.51Skamil } else { 24201.51Skamil DPRINTF("Tell the tracer child should have exited\n"); 24211.51Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 24221.51Skamil DPRINTF("Wait for tracer to finish its job and exit - calling " 24231.59Skamil "%s()\n", TWAIT_FNAME); 24241.51Skamil 24251.51Skamil DPRINTF("Wait from tracer child to complete waiting for " 24261.59Skamil "tracee\n"); 24271.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 24281.51Skamil tracer); 24291.1Skamil 24301.51Skamil validate_status_exited(status, exitval_tracer); 24311.51Skamil } 24321.1Skamil 24331.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 24341.1Skamil TWAIT_FNAME); 24351.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24361.1Skamil 24371.1Skamil validate_status_exited(status, exitval_tracee); 24381.1Skamil 24391.1Skamil msg_close(&parent_tracer); 24401.1Skamil msg_close(&parent_tracee); 24411.1Skamil} 24421.26Skamil 24431.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent); 24441.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc) 24451.51Skamil{ 24461.51Skamil atf_tc_set_md_var(tc, "descr", 24471.51Skamil "Assert that tracer sees process termination before the parent"); 24481.51Skamil} 24491.51Skamil 24501.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc) 24511.26Skamil{ 24521.26Skamil 24531.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, false, false); 24541.26Skamil} 24551.26Skamil 24561.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates); 24571.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc) 24581.1Skamil{ 24591.1Skamil atf_tc_set_md_var(tc, "descr", 24601.51Skamil "Assert that await_zombie() in attach1 always finds a single " 24611.51Skamil "process and no other error is reported"); 24621.1Skamil} 24631.1Skamil 24641.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc) 24651.1Skamil{ 24661.51Skamil time_t start, end; 24671.51Skamil double diff; 24681.51Skamil unsigned long N = 0; 24691.1Skamil 24701.51Skamil /* 24711.51Skamil * Reuse this test with tracer_sees_terminaton_before_the_parent_raw(). 24721.51Skamil * This test body isn't specific to this race, however it's just good 24731.51Skamil * enough for this purposes, no need to invent a dedicated code flow. 24741.51Skamil */ 24751.1Skamil 24761.51Skamil start = time(NULL); 24771.51Skamil while (true) { 24781.51Skamil DPRINTF("Step: %lu\n", N); 24791.67Skamil tracer_sees_terminaton_before_the_parent_raw(true, false, 24801.67Skamil false); 24811.51Skamil end = time(NULL); 24821.51Skamil diff = difftime(end, start); 24831.51Skamil if (diff >= 5.0) 24841.51Skamil break; 24851.51Skamil ++N; 24861.1Skamil } 24871.51Skamil DPRINTF("Iterations: %lu\n", N); 24881.51Skamil} 24891.1Skamil 24901.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent); 24911.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc) 24921.51Skamil{ 24931.51Skamil atf_tc_set_md_var(tc, "descr", 24941.51Skamil "Assert that tracer sees process termination before the parent"); 24951.51Skamil} 24961.1Skamil 24971.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc) 24981.51Skamil{ 24991.1Skamil 25001.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, false); 25011.67Skamil} 25021.67Skamil 25031.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process); 25041.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc) 25051.67Skamil{ 25061.67Skamil atf_tc_set_md_var(tc, "descr", 25071.67Skamil "Assert that tracer can attach to an unrelated stopped process"); 25081.67Skamil} 25091.67Skamil 25101.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc) 25111.67Skamil{ 25121.67Skamil 25131.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, true); 25141.1Skamil} 25151.1Skamil#endif 25161.1Skamil 25171.51Skamil/// ---------------------------------------------------------------------------- 25181.51Skamil 25191.66Skamilstatic void 25201.66Skamilparent_attach_to_its_child(bool stopped) 25211.1Skamil{ 25221.1Skamil struct msg_fds parent_tracee; 25231.1Skamil const int exitval_tracee = 5; 25241.1Skamil pid_t tracee, wpid; 25251.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 25261.1Skamil#if defined(TWAIT_HAVE_STATUS) 25271.1Skamil int status; 25281.1Skamil#endif 25291.1Skamil 25301.13Schristos DPRINTF("Spawn tracee\n"); 25311.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 25321.1Skamil tracee = atf_utils_fork(); 25331.1Skamil if (tracee == 0) { 25341.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 25351.13Schristos DPRINTF("Parent should now attach to tracee\n"); 25361.1Skamil 25371.66Skamil if (stopped) { 25381.66Skamil DPRINTF("Stop self PID %d\n", getpid()); 25391.66Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 25401.66Skamil } 25411.66Skamil 25421.1Skamil CHILD_FROM_PARENT("Message 2", parent_tracee, msg); 25431.1Skamil /* Wait for message from the parent */ 25441.1Skamil _exit(exitval_tracee); 25451.1Skamil } 25461.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 25471.57Skamil 25481.66Skamil if (stopped) { 25491.66Skamil DPRINTF("Await for a stopped tracee PID %d\n", tracee); 25501.66Skamil await_stopped(tracee); 25511.66Skamil } 25521.66Skamil 25531.13Schristos DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee); 25541.13Schristos SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 25551.1Skamil 25561.13Schristos DPRINTF("Wait for the stopped tracee process with %s()\n", 25571.1Skamil TWAIT_FNAME); 25581.1Skamil TWAIT_REQUIRE_SUCCESS( 25591.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25601.1Skamil 25611.1Skamil validate_status_stopped(status, SIGSTOP); 25621.1Skamil 25631.13Schristos DPRINTF("Resume tracee with PT_CONTINUE\n"); 25641.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 25651.1Skamil 25661.13Schristos DPRINTF("Let the tracee exit now\n"); 25671.1Skamil PARENT_TO_CHILD("Message 2", parent_tracee, msg); 25681.1Skamil 25691.13Schristos DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME); 25701.1Skamil TWAIT_REQUIRE_SUCCESS( 25711.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25721.1Skamil 25731.1Skamil validate_status_exited(status, exitval_tracee); 25741.1Skamil 25751.13Schristos DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME); 25761.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 25771.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0)); 25781.1Skamil 25791.1Skamil msg_close(&parent_tracee); 25801.1Skamil} 25811.1Skamil 25821.66SkamilATF_TC(parent_attach_to_its_child); 25831.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc) 25841.66Skamil{ 25851.66Skamil atf_tc_set_md_var(tc, "descr", 25861.66Skamil "Assert that tracer parent can PT_ATTACH to its child"); 25871.66Skamil} 25881.66Skamil 25891.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc) 25901.66Skamil{ 25911.66Skamil 25921.66Skamil parent_attach_to_its_child(false); 25931.66Skamil} 25941.66Skamil 25951.66SkamilATF_TC(parent_attach_to_its_stopped_child); 25961.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc) 25971.66Skamil{ 25981.66Skamil atf_tc_set_md_var(tc, "descr", 25991.66Skamil "Assert that tracer parent can PT_ATTACH to its stopped child"); 26001.66Skamil} 26011.66Skamil 26021.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc) 26031.66Skamil{ 26041.66Skamil 26051.66Skamil parent_attach_to_its_child(true); 26061.66Skamil} 26071.66Skamil 26081.51Skamil/// ---------------------------------------------------------------------------- 26091.51Skamil 26101.65Skamilstatic void 26111.65Skamilchild_attach_to_its_parent(bool stopped) 26121.1Skamil{ 26131.1Skamil struct msg_fds parent_tracee; 26141.1Skamil const int exitval_tracer = 5; 26151.1Skamil pid_t tracer, wpid; 26161.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 26171.1Skamil#if defined(TWAIT_HAVE_STATUS) 26181.1Skamil int status; 26191.1Skamil#endif 26201.1Skamil 26211.13Schristos DPRINTF("Spawn tracer\n"); 26221.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 26231.1Skamil tracer = atf_utils_fork(); 26241.1Skamil if (tracer == 0) { 26251.1Skamil /* Wait for message from the parent */ 26261.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 26271.1Skamil 26281.65Skamil if (stopped) { 26291.65Skamil DPRINTF("Await for a stopped parent PID %d\n", 26301.65Skamil getppid()); 26311.65Skamil await_stopped(getppid()); 26321.65Skamil } 26331.65Skamil 26341.13Schristos DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n", 26351.1Skamil getppid()); 26361.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1); 26371.1Skamil 26381.13Schristos DPRINTF("Wait for the stopped parent process with %s()\n", 26391.1Skamil TWAIT_FNAME); 26401.1Skamil FORKEE_REQUIRE_SUCCESS( 26411.1Skamil wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid()); 26421.1Skamil 26431.1Skamil forkee_status_stopped(status, SIGSTOP); 26441.1Skamil 26451.13Schristos DPRINTF("Resume parent with PT_DETACH\n"); 26461.1Skamil FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0) 26471.1Skamil != -1); 26481.1Skamil 26491.1Skamil /* Tell parent we are ready */ 26501.1Skamil CHILD_TO_PARENT("Message 1", parent_tracee, msg); 26511.1Skamil 26521.1Skamil _exit(exitval_tracer); 26531.1Skamil } 26541.1Skamil 26551.13Schristos DPRINTF("Wait for the tracer to become ready\n"); 26561.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 26571.65Skamil 26581.65Skamil if (stopped) { 26591.65Skamil DPRINTF("Stop self PID %d\n", getpid()); 26601.65Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 26611.65Skamil } 26621.65Skamil 26631.13Schristos DPRINTF("Allow the tracer to exit now\n"); 26641.1Skamil PARENT_FROM_CHILD("Message 1", parent_tracee, msg); 26651.1Skamil 26661.13Schristos DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME); 26671.1Skamil TWAIT_REQUIRE_SUCCESS( 26681.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 26691.1Skamil 26701.1Skamil validate_status_exited(status, exitval_tracer); 26711.1Skamil 26721.13Schristos DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME); 26731.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 26741.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0)); 26751.1Skamil 26761.1Skamil msg_close(&parent_tracee); 26771.1Skamil} 26781.1Skamil 26791.65SkamilATF_TC(child_attach_to_its_parent); 26801.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc) 26811.65Skamil{ 26821.65Skamil atf_tc_set_md_var(tc, "descr", 26831.65Skamil "Assert that tracer child can PT_ATTACH to its parent"); 26841.65Skamil} 26851.65Skamil 26861.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc) 26871.65Skamil{ 26881.65Skamil 26891.65Skamil child_attach_to_its_parent(false); 26901.65Skamil} 26911.65Skamil 26921.65SkamilATF_TC(child_attach_to_its_stopped_parent); 26931.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc) 26941.65Skamil{ 26951.65Skamil atf_tc_set_md_var(tc, "descr", 26961.65Skamil "Assert that tracer child can PT_ATTACH to its stopped parent"); 26971.65Skamil} 26981.65Skamil 26991.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc) 27001.65Skamil{ 27011.65Skamil /* 27021.65Skamil * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as 27031.65Skamil * this causes a pipe (established from atf-run) to be broken. 27041.65Skamil * atf-run uses this mechanism to monitor whether a test is alive. 27051.65Skamil * 27061.65Skamil * As a workaround spawn this test as a subprocess. 27071.65Skamil */ 27081.65Skamil 27091.65Skamil const int exitval = 15; 27101.65Skamil pid_t child, wpid; 27111.65Skamil#if defined(TWAIT_HAVE_STATUS) 27121.65Skamil int status; 27131.65Skamil#endif 27141.65Skamil 27151.65Skamil SYSCALL_REQUIRE((child = fork()) != -1); 27161.65Skamil if (child == 0) { 27171.65Skamil child_attach_to_its_parent(true); 27181.65Skamil _exit(exitval); 27191.65Skamil } else { 27201.65Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 27211.65Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 27221.65Skamil 27231.65Skamil validate_status_exited(status, exitval); 27241.65Skamil 27251.65Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 27261.65Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 27271.65Skamil } 27281.65Skamil} 27291.65Skamil 27301.51Skamil/// ---------------------------------------------------------------------------- 27311.51Skamil 27321.1Skamil#if defined(TWAIT_HAVE_PID) 27331.1Skamil 27341.51Skamilenum tracee_sees_its_original_parent_type { 27351.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 27361.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 27371.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS 27381.51Skamil}; 27391.51Skamil 27401.51Skamilstatic void 27411.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type) 27421.1Skamil{ 27431.1Skamil struct msg_fds parent_tracer, parent_tracee; 27441.1Skamil const int exitval_tracee = 5; 27451.1Skamil const int exitval_tracer = 10; 27461.1Skamil pid_t parent, tracee, tracer, wpid; 27471.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 27481.1Skamil#if defined(TWAIT_HAVE_STATUS) 27491.1Skamil int status; 27501.1Skamil#endif 27511.51Skamil /* sysctl(3) - kinfo_proc2 */ 27521.51Skamil int name[CTL_MAXNAME]; 27531.51Skamil struct kinfo_proc2 kp; 27541.51Skamil size_t len = sizeof(kp); 27551.51Skamil unsigned int namelen; 27561.51Skamil 27571.51Skamil /* procfs - status */ 27581.51Skamil FILE *fp; 27591.51Skamil struct stat st; 27601.51Skamil const char *fname = "/proc/curproc/status"; 27611.51Skamil char s_executable[MAXPATHLEN]; 27621.51Skamil int s_pid, s_ppid; 27631.51Skamil int rv; 27641.51Skamil 27651.51Skamil if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) { 27661.61Skre SYSCALL_REQUIRE( 27671.61Skre (rv = stat(fname, &st)) == 0 || (errno == ENOENT)); 27681.61Skre if (rv != 0) 27691.51Skamil atf_tc_skip("/proc/curproc/status not found"); 27701.51Skamil } 27711.1Skamil 27721.13Schristos DPRINTF("Spawn tracee\n"); 27731.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 27741.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 27751.1Skamil tracee = atf_utils_fork(); 27761.1Skamil if (tracee == 0) { 27771.1Skamil parent = getppid(); 27781.1Skamil 27791.1Skamil /* Emit message to the parent */ 27801.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 27811.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 27821.1Skamil 27831.51Skamil switch (type) { 27841.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID: 27851.51Skamil FORKEE_ASSERT_EQ(parent, getppid()); 27861.51Skamil break; 27871.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2: 27881.51Skamil namelen = 0; 27891.51Skamil name[namelen++] = CTL_KERN; 27901.51Skamil name[namelen++] = KERN_PROC2; 27911.51Skamil name[namelen++] = KERN_PROC_PID; 27921.51Skamil name[namelen++] = getpid(); 27931.51Skamil name[namelen++] = len; 27941.51Skamil name[namelen++] = 1; 27951.51Skamil 27961.61Skre FORKEE_ASSERT_EQ( 27971.61Skre sysctl(name, namelen, &kp, &len, NULL, 0), 0); 27981.51Skamil FORKEE_ASSERT_EQ(parent, kp.p_ppid); 27991.51Skamil break; 28001.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS: 28011.51Skamil /* 28021.51Skamil * Format: 28031.51Skamil * EXECUTABLE PID PPID ... 28041.51Skamil */ 28051.51Skamil FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL); 28061.51Skamil fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid); 28071.51Skamil FORKEE_ASSERT_EQ(fclose(fp), 0); 28081.51Skamil FORKEE_ASSERT_EQ(parent, s_ppid); 28091.51Skamil break; 28101.51Skamil } 28111.1Skamil 28121.1Skamil _exit(exitval_tracee); 28131.1Skamil } 28141.13Schristos DPRINTF("Wait for child to record its parent identifier (pid)\n"); 28151.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 28161.1Skamil 28171.13Schristos DPRINTF("Spawn debugger\n"); 28181.1Skamil tracer = atf_utils_fork(); 28191.1Skamil if (tracer == 0) { 28201.1Skamil /* No IPC to communicate with the child */ 28211.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 28221.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 28231.1Skamil 28241.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 28251.1Skamil FORKEE_REQUIRE_SUCCESS( 28261.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28271.1Skamil 28281.1Skamil forkee_status_stopped(status, SIGSTOP); 28291.1Skamil 28301.1Skamil /* Resume tracee with PT_CONTINUE */ 28311.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 28321.1Skamil 28331.1Skamil /* Inform parent that tracer has attached to tracee */ 28341.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 28351.1Skamil 28361.1Skamil /* Wait for parent to tell use that tracee should have exited */ 28371.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 28381.1Skamil 28391.1Skamil /* Wait for tracee and assert that it exited */ 28401.1Skamil FORKEE_REQUIRE_SUCCESS( 28411.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28421.1Skamil 28431.1Skamil forkee_status_exited(status, exitval_tracee); 28441.1Skamil 28451.13Schristos DPRINTF("Before exiting of the tracer process\n"); 28461.1Skamil _exit(exitval_tracer); 28471.1Skamil } 28481.1Skamil 28491.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 28501.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 28511.1Skamil 28521.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 28531.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 28541.1Skamil 28551.13Schristos DPRINTF("Detect that tracee is zombie\n"); 28561.1Skamil await_zombie(tracee); 28571.1Skamil 28581.13Schristos DPRINTF("Assert that there is no status about tracee - " 28591.1Skamil "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME); 28601.1Skamil TWAIT_REQUIRE_SUCCESS( 28611.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 28621.1Skamil 28631.13Schristos DPRINTF("Tell the tracer child should have exited\n"); 28641.1Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 28651.1Skamil 28661.13Schristos DPRINTF("Wait from tracer child to complete waiting for tracee\n"); 28671.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 28681.1Skamil tracer); 28691.1Skamil 28701.1Skamil validate_status_exited(status, exitval_tracer); 28711.1Skamil 28721.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 28731.1Skamil TWAIT_FNAME); 28741.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 28751.1Skamil tracee); 28761.1Skamil 28771.1Skamil validate_status_exited(status, exitval_tracee); 28781.1Skamil 28791.1Skamil msg_close(&parent_tracer); 28801.1Skamil msg_close(&parent_tracee); 28811.1Skamil} 28821.1Skamil 28831.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr) \ 28841.61SkreATF_TC(test); \ 28851.61SkreATF_TC_HEAD(test, tc) \ 28861.61Skre{ \ 28871.61Skre atf_tc_set_md_var(tc, "descr", \ 28881.61Skre "Assert that tracee sees its original parent when being traced " \ 28891.61Skre "(check " descr ")"); \ 28901.61Skre} \ 28911.61Skre \ 28921.61SkreATF_TC_BODY(test, tc) \ 28931.61Skre{ \ 28941.61Skre \ 28951.61Skre tracee_sees_its_original_parent(type); \ 28961.1Skamil} 28971.1Skamil 28981.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 28991.51Skamil tracee_sees_its_original_parent_getppid, 29001.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 29011.51Skamil "getppid(2)"); 29021.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29031.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2, 29041.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 29051.51Skamil "sysctl(3) and kinfo_proc2"); 29061.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29071.51Skamil tracee_sees_its_original_parent_procfs_status, 29081.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS, 29091.51Skamil "the status file in procfs"); 29101.1Skamil#endif 29111.1Skamil 29121.51Skamil/// ---------------------------------------------------------------------------- 29131.1Skamil 29141.53Skamilstatic void 29151.53Skamileventmask_preserved(int event) 29161.1Skamil{ 29171.1Skamil const int exitval = 5; 29181.1Skamil const int sigval = SIGSTOP; 29191.1Skamil pid_t child, wpid; 29201.1Skamil#if defined(TWAIT_HAVE_STATUS) 29211.1Skamil int status; 29221.1Skamil#endif 29231.1Skamil ptrace_event_t set_event, get_event; 29241.1Skamil const int len = sizeof(ptrace_event_t); 29251.1Skamil 29261.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 29271.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 29281.1Skamil if (child == 0) { 29291.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 29301.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 29311.1Skamil 29321.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 29331.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 29341.1Skamil 29351.13Schristos DPRINTF("Before exiting of the child process\n"); 29361.1Skamil _exit(exitval); 29371.1Skamil } 29381.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 29391.1Skamil 29401.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29411.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29421.1Skamil 29431.1Skamil validate_status_stopped(status, sigval); 29441.1Skamil 29451.53Skamil set_event.pe_set_event = event; 29461.61Skre SYSCALL_REQUIRE( 29471.61Skre ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); 29481.61Skre SYSCALL_REQUIRE( 29491.61Skre ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); 29501.125Skamil DPRINTF("set_event=%#x get_event=%#x\n", set_event.pe_set_event, 29511.125Skamil get_event.pe_set_event); 29521.1Skamil ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); 29531.1Skamil 29541.13Schristos DPRINTF("Before resuming the child process where it left off and " 29551.1Skamil "without signal to be sent\n"); 29561.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 29571.1Skamil 29581.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29591.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29601.1Skamil 29611.1Skamil validate_status_exited(status, exitval); 29621.1Skamil 29631.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29641.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 29651.1Skamil} 29661.1Skamil 29671.61Skre#define EVENTMASK_PRESERVED(test, event) \ 29681.61SkreATF_TC(test); \ 29691.61SkreATF_TC_HEAD(test, tc) \ 29701.61Skre{ \ 29711.61Skre atf_tc_set_md_var(tc, "descr", \ 29721.61Skre "Verify that eventmask " #event " is preserved"); \ 29731.61Skre} \ 29741.61Skre \ 29751.61SkreATF_TC_BODY(test, tc) \ 29761.61Skre{ \ 29771.61Skre \ 29781.61Skre eventmask_preserved(event); \ 29791.1Skamil} 29801.1Skamil 29811.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0) 29821.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK) 29831.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK) 29841.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE) 29851.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE) 29861.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT) 29871.125SkamilEVENTMASK_PRESERVED(eventmask_preserved_posix_spawn, PTRACE_POSIX_SPAWN) 29881.1Skamil 29891.53Skamil/// ---------------------------------------------------------------------------- 29901.1Skamil 29911.28Skamilstatic void 29921.125Skamilfork_body(const char *fn, bool trackspawn, bool trackfork, bool trackvfork, 29931.105Skamil bool trackvforkdone) 29941.1Skamil{ 29951.1Skamil const int exitval = 5; 29961.125Skamil const int exitval2 = 0; /* This matched exit status from /bin/echo */ 29971.1Skamil const int sigval = SIGSTOP; 29981.31Skamil pid_t child, child2 = 0, wpid; 29991.1Skamil#if defined(TWAIT_HAVE_STATUS) 30001.1Skamil int status; 30011.1Skamil#endif 30021.1Skamil ptrace_state_t state; 30031.1Skamil const int slen = sizeof(state); 30041.1Skamil ptrace_event_t event; 30051.1Skamil const int elen = sizeof(event); 30061.1Skamil 30071.124Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 30081.124Skamil 30091.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 30101.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 30111.1Skamil if (child == 0) { 30121.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 30131.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 30141.1Skamil 30151.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 30161.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 30171.1Skamil 30181.125Skamil if (strcmp(fn, "spawn") == 0) { 30191.124Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 30201.124Skamil arg[0], NULL, NULL, arg, NULL), 0); 30211.125Skamil } else { 30221.125Skamil if (strcmp(fn, "fork") == 0) { 30231.125Skamil FORKEE_ASSERT((child2 = fork()) != -1); 30241.125Skamil } else if (strcmp(fn, "vfork") == 0) { 30251.125Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 30261.125Skamil } 30271.1Skamil 30281.124Skamil if (child2 == 0) 30291.124Skamil _exit(exitval2); 30301.124Skamil } 30311.1Skamil FORKEE_REQUIRE_SUCCESS 30321.1Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 30331.1Skamil 30341.1Skamil forkee_status_exited(status, exitval2); 30351.1Skamil 30361.13Schristos DPRINTF("Before exiting of the child process\n"); 30371.1Skamil _exit(exitval); 30381.1Skamil } 30391.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 30401.1Skamil 30411.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 30421.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 30431.1Skamil 30441.1Skamil validate_status_stopped(status, sigval); 30451.1Skamil 30461.125Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 30471.125Skamil trackspawn ? "|PTRACE_POSIX_SPAWN" : "", 30481.61Skre trackfork ? "|PTRACE_FORK" : "", 30491.61Skre trackvfork ? "|PTRACE_VFORK" : "", 30501.61Skre trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 30511.30Skamil event.pe_set_event = 0; 30521.125Skamil if (trackspawn) 30531.125Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 30541.30Skamil if (trackfork) 30551.30Skamil event.pe_set_event |= PTRACE_FORK; 30561.30Skamil if (trackvfork) 30571.30Skamil event.pe_set_event |= PTRACE_VFORK; 30581.30Skamil if (trackvforkdone) 30591.30Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 30601.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 30611.1Skamil 30621.13Schristos DPRINTF("Before resuming the child process where it left off and " 30631.1Skamil "without signal to be sent\n"); 30641.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 30651.1Skamil 30661.29Skamil#if defined(TWAIT_HAVE_PID) 30671.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 30681.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 30691.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 30701.29Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 30711.61Skre child); 30721.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 30731.61Skre child); 30741.1Skamil 30751.29Skamil validate_status_stopped(status, SIGTRAP); 30761.1Skamil 30771.61Skre SYSCALL_REQUIRE( 30781.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 30791.125Skamil if (trackspawn && strcmp(fn, "spawn") == 0) { 30801.125Skamil ATF_REQUIRE_EQ( 30811.125Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 30821.125Skamil PTRACE_POSIX_SPAWN); 30831.125Skamil } 30841.125Skamil if (trackfork && strcmp(fn, "fork") == 0) { 30851.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 30861.30Skamil PTRACE_FORK); 30871.30Skamil } 30881.125Skamil if (trackvfork && strcmp(fn, "vfork") == 0) { 30891.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 30901.30Skamil PTRACE_VFORK); 30911.30Skamil } 30921.29Skamil 30931.29Skamil child2 = state.pe_other_pid; 30941.30Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 30951.29Skamil 30961.29Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 30971.61Skre "%d\n", TWAIT_FNAME, child2, child); 30981.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 30991.29Skamil child2); 31001.1Skamil 31011.29Skamil validate_status_stopped(status, SIGTRAP); 31021.1Skamil 31031.61Skre SYSCALL_REQUIRE( 31041.61Skre ptrace(PT_GET_PROCESS_STATE, child2, &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.30Skamil 31191.29Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 31201.29Skamil 31211.29Skamil DPRINTF("Before resuming the forkee process where it left off " 31221.29Skamil "and without signal to be sent\n"); 31231.61Skre SYSCALL_REQUIRE( 31241.61Skre ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 31251.29Skamil 31261.29Skamil DPRINTF("Before resuming the child process where it left off " 31271.61Skre "and without signal to be sent\n"); 31281.29Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31291.30Skamil } 31301.30Skamil#endif 31311.30Skamil 31321.125Skamil if (trackvforkdone && strcmp(fn, "vfork") == 0) { 31331.30Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 31341.61Skre child); 31351.61Skre TWAIT_REQUIRE_SUCCESS( 31361.61Skre wpid = TWAIT_GENERIC(child, &status, 0), child); 31371.30Skamil 31381.30Skamil validate_status_stopped(status, SIGTRAP); 31391.30Skamil 31401.61Skre SYSCALL_REQUIRE( 31411.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 31421.30Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 31431.30Skamil 31441.30Skamil child2 = state.pe_other_pid; 31451.30Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 31461.61Skre child2); 31471.30Skamil 31481.30Skamil DPRINTF("Before resuming the child process where it left off " 31491.61Skre "and without signal to be sent\n"); 31501.30Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31511.30Skamil } 31521.29Skamil 31531.30Skamil#if defined(TWAIT_HAVE_PID) 31541.125Skamil if ((trackspawn && strcmp(fn, "spawn") == 0) || 31551.125Skamil (trackfork && strcmp(fn, "fork") == 0) || 31561.125Skamil (trackvfork && strcmp(fn, "vfork") == 0)) { 31571.29Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 31581.61Skre "\n", TWAIT_FNAME); 31591.61Skre TWAIT_REQUIRE_SUCCESS( 31601.61Skre wpid = TWAIT_GENERIC(child2, &status, 0), child2); 31611.29Skamil 31621.29Skamil validate_status_exited(status, exitval2); 31631.29Skamil 31641.29Skamil DPRINTF("Before calling %s() for the forkee - expected no " 31651.61Skre "process\n", TWAIT_FNAME); 31661.29Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 31671.29Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 31681.29Skamil } 31691.29Skamil#endif 31701.1Skamil 31711.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 31721.1Skamil "SIGCHLD\n", TWAIT_FNAME); 31731.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31741.1Skamil 31751.1Skamil validate_status_stopped(status, SIGCHLD); 31761.1Skamil 31771.13Schristos DPRINTF("Before resuming the child process where it left off and " 31781.1Skamil "without signal to be sent\n"); 31791.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31801.1Skamil 31811.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 31821.1Skamil TWAIT_FNAME); 31831.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31841.1Skamil 31851.1Skamil validate_status_exited(status, exitval); 31861.1Skamil 31871.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 31881.1Skamil TWAIT_FNAME); 31891.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 31901.1Skamil} 31911.28Skamil 31921.125Skamil#define FORK_TEST(name,fun,tspawn,tfork,tvfork,tvforkdone) \ 31931.61SkreATF_TC(name); \ 31941.61SkreATF_TC_HEAD(name, tc) \ 31951.61Skre{ \ 31961.125Skamil atf_tc_set_md_var(tc, "descr", "Verify " fun "() " \ 31971.125Skamil "called with 0%s%s%s%s in EVENT_MASK", \ 31981.126Skamil tspawn ? "|PTRACE_POSIX_SPAWN" : "", \ 31991.105Skamil tfork ? "|PTRACE_FORK" : "", \ 32001.105Skamil tvfork ? "|PTRACE_VFORK" : "", \ 32011.105Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 32021.61Skre} \ 32031.61Skre \ 32041.61SkreATF_TC_BODY(name, tc) \ 32051.61Skre{ \ 32061.61Skre \ 32071.125Skamil fork_body(fun, tspawn, tfork, tvfork, tvforkdone); \ 32081.32Skamil} 32091.32Skamil 32101.125SkamilFORK_TEST(fork1, "fork", false, false, false, false) 32111.31Skamil#if defined(TWAIT_HAVE_PID) 32121.125SkamilFORK_TEST(fork2, "fork", false, true, false, false) 32131.125SkamilFORK_TEST(fork3, "fork", false, false, true, false) 32141.125SkamilFORK_TEST(fork4, "fork", false, true, true, false) 32151.31Skamil#endif 32161.125SkamilFORK_TEST(fork5, "fork", false, false, false, true) 32171.31Skamil#if defined(TWAIT_HAVE_PID) 32181.125SkamilFORK_TEST(fork6, "fork", false, true, false, true) 32191.125SkamilFORK_TEST(fork7, "fork", false, false, true, true) 32201.125SkamilFORK_TEST(fork8, "fork", false, true, true, true) 32211.125Skamil#endif 32221.125SkamilFORK_TEST(fork9, "fork", true, false, false, false) 32231.125Skamil#if defined(TWAIT_HAVE_PID) 32241.125SkamilFORK_TEST(fork10, "fork", true, true, false, false) 32251.125SkamilFORK_TEST(fork11, "fork", true, false, true, false) 32261.125SkamilFORK_TEST(fork12, "fork", true, true, true, false) 32271.125Skamil#endif 32281.125SkamilFORK_TEST(fork13, "fork", true, false, false, true) 32291.125Skamil#if defined(TWAIT_HAVE_PID) 32301.125SkamilFORK_TEST(fork14, "fork", true, true, false, true) 32311.125SkamilFORK_TEST(fork15, "fork", true, false, true, true) 32321.125SkamilFORK_TEST(fork16, "fork", true, true, true, true) 32331.31Skamil#endif 32341.1Skamil 32351.110Skamil#if TEST_VFORK_ENABLED 32361.125SkamilFORK_TEST(vfork1, "vfork", false, false, false, false) 32371.31Skamil#if defined(TWAIT_HAVE_PID) 32381.125SkamilFORK_TEST(vfork2, "vfork", false, true, false, false) 32391.125SkamilFORK_TEST(vfork3, "vfork", false, false, true, false) 32401.125SkamilFORK_TEST(vfork4, "vfork", false, true, true, false) 32411.31Skamil#endif 32421.125SkamilFORK_TEST(vfork5, "vfork", false, false, false, true) 32431.31Skamil#if defined(TWAIT_HAVE_PID) 32441.125SkamilFORK_TEST(vfork6, "vfork", false, true, false, true) 32451.125SkamilFORK_TEST(vfork7, "vfork", false, false, true, true) 32461.125SkamilFORK_TEST(vfork8, "vfork", false, true, true, true) 32471.31Skamil#endif 32481.125SkamilFORK_TEST(vfork9, "vfork", true, false, false, false) 32491.125Skamil#if defined(TWAIT_HAVE_PID) 32501.125SkamilFORK_TEST(vfork10, "vfork", true, true, false, false) 32511.125SkamilFORK_TEST(vfork11, "vfork", true, false, true, false) 32521.125SkamilFORK_TEST(vfork12, "vfork", true, true, true, false) 32531.110Skamil#endif 32541.125SkamilFORK_TEST(vfork13, "vfork", true, false, false, true) 32551.124Skamil#if defined(TWAIT_HAVE_PID) 32561.125SkamilFORK_TEST(vfork14, "vfork", true, true, false, true) 32571.125SkamilFORK_TEST(vfork15, "vfork", true, false, true, true) 32581.125SkamilFORK_TEST(vfork16, "vfork", true, true, true, true) 32591.124Skamil#endif 32601.125Skamil#endif 32611.125Skamil 32621.125SkamilFORK_TEST(posix_spawn1, "spawn", false, false, false, false) 32631.125SkamilFORK_TEST(posix_spawn2, "spawn", false, true, false, false) 32641.125SkamilFORK_TEST(posix_spawn3, "spawn", false, false, true, false) 32651.125SkamilFORK_TEST(posix_spawn4, "spawn", false, true, true, false) 32661.125SkamilFORK_TEST(posix_spawn5, "spawn", false, false, false, true) 32671.125SkamilFORK_TEST(posix_spawn6, "spawn", false, true, false, true) 32681.125SkamilFORK_TEST(posix_spawn7, "spawn", false, false, true, true) 32691.125SkamilFORK_TEST(posix_spawn8, "spawn", false, true, true, true) 32701.124Skamil#if defined(TWAIT_HAVE_PID) 32711.125SkamilFORK_TEST(posix_spawn9, "spawn", true, false, false, false) 32721.125SkamilFORK_TEST(posix_spawn10, "spawn", true, true, false, false) 32731.125SkamilFORK_TEST(posix_spawn11, "spawn", true, false, true, false) 32741.125SkamilFORK_TEST(posix_spawn12, "spawn", true, true, true, false) 32751.125SkamilFORK_TEST(posix_spawn13, "spawn", true, false, false, true) 32761.125SkamilFORK_TEST(posix_spawn14, "spawn", true, true, false, true) 32771.125SkamilFORK_TEST(posix_spawn15, "spawn", true, false, true, true) 32781.125SkamilFORK_TEST(posix_spawn16, "spawn", true, true, true, true) 32791.124Skamil#endif 32801.124Skamil 32811.54Skamil/// ---------------------------------------------------------------------------- 32821.31Skamil 32831.116Skamil#if defined(TWAIT_HAVE_PID) 32841.116Skamilstatic void 32851.126Skamilfork_detach_forker_body(const char *fn, bool kill_process) 32861.116Skamil{ 32871.116Skamil const int exitval = 5; 32881.126Skamil const int exitval2 = 0; /* Matches exit value from /bin/echo */ 32891.116Skamil const int sigval = SIGSTOP; 32901.116Skamil pid_t child, child2 = 0, wpid; 32911.116Skamil#if defined(TWAIT_HAVE_STATUS) 32921.116Skamil int status; 32931.116Skamil#endif 32941.116Skamil ptrace_state_t state; 32951.116Skamil const int slen = sizeof(state); 32961.116Skamil ptrace_event_t event; 32971.116Skamil const int elen = sizeof(event); 32981.116Skamil 32991.116Skamil int op; 33001.116Skamil 33011.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 33021.116Skamil 33031.116Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 33041.116Skamil SYSCALL_REQUIRE((child = fork()) != -1); 33051.116Skamil if (child == 0) { 33061.116Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 33071.116Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 33081.116Skamil 33091.116Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 33101.116Skamil FORKEE_ASSERT(raise(sigval) == 0); 33111.116Skamil 33121.126Skamil if (strcmp(fn, "spawn") == 0) { 33131.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 33141.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 33151.126Skamil } else { 33161.126Skamil if (strcmp(fn, "fork") == 0) { 33171.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 33181.126Skamil } else { 33191.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 33201.126Skamil } 33211.116Skamil 33221.126Skamil if (child2 == 0) 33231.126Skamil _exit(exitval2); 33241.126Skamil } 33251.116Skamil 33261.116Skamil FORKEE_REQUIRE_SUCCESS 33271.116Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 33281.116Skamil 33291.116Skamil forkee_status_exited(status, exitval2); 33301.116Skamil 33311.116Skamil DPRINTF("Before exiting of the child process\n"); 33321.116Skamil _exit(exitval); 33331.116Skamil } 33341.116Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 33351.116Skamil 33361.116Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 33371.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33381.116Skamil 33391.116Skamil validate_status_stopped(status, sigval); 33401.116Skamil 33411.116Skamil DPRINTF("Set EVENT_MASK for the child %d\n", child); 33421.126Skamil event.pe_set_event = PTRACE_POSIX_SPAWN | PTRACE_FORK | PTRACE_VFORK 33431.126Skamil | PTRACE_VFORK_DONE; 33441.116Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 33451.116Skamil 33461.116Skamil DPRINTF("Before resuming the child process where it left off and " 33471.116Skamil "without signal to be sent\n"); 33481.116Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 33491.116Skamil 33501.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child); 33511.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33521.116Skamil 33531.116Skamil validate_status_stopped(status, SIGTRAP); 33541.116Skamil 33551.116Skamil SYSCALL_REQUIRE( 33561.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 33571.126Skamil 33581.126Skamil if (strcmp(fn, "spawn") == 0) 33591.126Skamil op = PTRACE_POSIX_SPAWN; 33601.126Skamil else if (strcmp(fn, "fork") == 0) 33611.126Skamil op = PTRACE_FORK; 33621.126Skamil else 33631.126Skamil op = PTRACE_VFORK; 33641.126Skamil 33651.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 33661.116Skamil 33671.116Skamil child2 = state.pe_other_pid; 33681.116Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 33691.116Skamil 33701.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 33711.126Skamil strcmp(fn, "vfork") == 0) 33721.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 33731.116Skamil else 33741.116Skamil op = PT_CONTINUE; 33751.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 33761.116Skamil 33771.116Skamil DPRINTF("Before calling %s() for the forkee %d of the child %d\n", 33781.116Skamil TWAIT_FNAME, child2, child); 33791.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 33801.116Skamil 33811.116Skamil validate_status_stopped(status, SIGTRAP); 33821.116Skamil 33831.116Skamil SYSCALL_REQUIRE( 33841.116Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 33851.126Skamil if (strcmp(fn, "spawn") == 0) 33861.126Skamil op = PTRACE_POSIX_SPAWN; 33871.126Skamil else if (strcmp(fn, "fork") == 0) 33881.126Skamil op = PTRACE_FORK; 33891.126Skamil else 33901.126Skamil op = PTRACE_VFORK; 33911.126Skamil 33921.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 33931.116Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 33941.116Skamil 33951.116Skamil DPRINTF("Before resuming the forkee process where it left off " 33961.116Skamil "and without signal to be sent\n"); 33971.116Skamil SYSCALL_REQUIRE( 33981.116Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 33991.116Skamil 34001.126Skamil if (strcmp(fn, "vforkdone") == 0) { 34011.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 34021.116Skamil child); 34031.116Skamil TWAIT_REQUIRE_SUCCESS( 34041.116Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 34051.116Skamil 34061.116Skamil validate_status_stopped(status, SIGTRAP); 34071.116Skamil 34081.116Skamil SYSCALL_REQUIRE( 34091.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 34101.116Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 34111.116Skamil 34121.116Skamil child2 = state.pe_other_pid; 34131.116Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 34141.116Skamil child2); 34151.116Skamil 34161.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 34171.116Skamil DPRINTF("Before resuming the child process where it left off " 34181.116Skamil "and without signal to be sent\n"); 34191.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 34201.116Skamil } 34211.116Skamil 34221.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 34231.116Skamil TWAIT_FNAME); 34241.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 34251.116Skamil 34261.116Skamil validate_status_exited(status, exitval2); 34271.116Skamil 34281.116Skamil DPRINTF("Before calling %s() for the forkee - expected no process\n", 34291.116Skamil TWAIT_FNAME); 34301.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child2, &status, 0)); 34311.116Skamil 34321.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 34331.116Skamil TWAIT_FNAME); 34341.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 34351.116Skamil 34361.116Skamil if (kill_process) { 34371.116Skamil validate_status_signaled(status, SIGKILL, 0); 34381.116Skamil } else { 34391.116Skamil validate_status_exited(status, exitval); 34401.116Skamil } 34411.116Skamil 34421.116Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 34431.116Skamil TWAIT_FNAME); 34441.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 34451.116Skamil} 34461.116Skamil 34471.126Skamil#define FORK_DETACH_FORKER(name,event,kprocess) \ 34481.116SkamilATF_TC(name); \ 34491.116SkamilATF_TC_HEAD(name, tc) \ 34501.116Skamil{ \ 34511.126Skamil atf_tc_set_md_var(tc, "descr", "Verify %s " event, \ 34521.126Skamil kprocess ? "killed" : "detached"); \ 34531.116Skamil} \ 34541.116Skamil \ 34551.116SkamilATF_TC_BODY(name, tc) \ 34561.116Skamil{ \ 34571.116Skamil \ 34581.126Skamil fork_detach_forker_body(event, kprocess); \ 34591.116Skamil} 34601.116Skamil 34611.126SkamilFORK_DETACH_FORKER(posix_spawn_detach_spawner, "spawn", false) 34621.126SkamilFORK_DETACH_FORKER(fork_detach_forker, "fork", false) 34631.116Skamil#if TEST_VFORK_ENABLED 34641.126SkamilFORK_DETACH_FORKER(vfork_detach_vforker, "vfork", false) 34651.126SkamilFORK_DETACH_FORKER(vfork_detach_vforkerdone, "vforkdone", false) 34661.116Skamil#endif 34671.126Skamil 34681.126SkamilFORK_DETACH_FORKER(posix_spawn_kill_spawner, "spawn", true) 34691.126SkamilFORK_DETACH_FORKER(fork_kill_forker, "fork", true) 34701.116Skamil#if TEST_VFORK_ENABLED 34711.126SkamilFORK_DETACH_FORKER(vfork_kill_vforker, "vfork", true) 34721.126SkamilFORK_DETACH_FORKER(vfork_kill_vforkerdone, "vforkdone", true) 34731.116Skamil#endif 34741.116Skamil#endif 34751.116Skamil 34761.116Skamil/// ---------------------------------------------------------------------------- 34771.116Skamil 34781.110Skamil#if TEST_VFORK_ENABLED 34791.108Skamilstatic void 34801.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void)) 34811.108Skamil{ 34821.108Skamil const int exitval = 5; 34831.108Skamil const int exitval2 = 15; 34841.108Skamil pid_t child, child2 = 0, wpid; 34851.108Skamil#if defined(TWAIT_HAVE_STATUS) 34861.108Skamil int status; 34871.108Skamil#endif 34881.108Skamil 34891.108Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 34901.108Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 34911.108Skamil if (child == 0) { 34921.108Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 34931.108Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 34941.108Skamil 34951.108Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 34961.108Skamil 34971.108Skamil if (child2 == 0) 34981.108Skamil _exit(exitval2); 34991.108Skamil 35001.108Skamil FORKEE_REQUIRE_SUCCESS 35011.108Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 35021.108Skamil 35031.108Skamil forkee_status_exited(status, exitval2); 35041.108Skamil 35051.108Skamil DPRINTF("Before exiting of the child process\n"); 35061.108Skamil _exit(exitval); 35071.108Skamil } 35081.108Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 35091.108Skamil 35101.108Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 35111.108Skamil TWAIT_FNAME); 35121.108Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 35131.108Skamil 35141.108Skamil validate_status_exited(status, exitval); 35151.108Skamil 35161.108Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 35171.108Skamil TWAIT_FNAME); 35181.108Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 35191.108Skamil} 35201.108Skamil 35211.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun) \ 35221.108SkamilATF_TC(name); \ 35231.108SkamilATF_TC_HEAD(name, tc) \ 35241.108Skamil{ \ 35251.108Skamil atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) " \ 35261.108Skamil "called from vfork(2)ed child"); \ 35271.108Skamil} \ 35281.108Skamil \ 35291.108SkamilATF_TC_BODY(name, tc) \ 35301.108Skamil{ \ 35311.108Skamil \ 35321.108Skamil traceme_vfork_fork_body(fun); \ 35331.108Skamil} 35341.108Skamil 35351.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork) 35361.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork) 35371.110Skamil#endif 35381.108Skamil 35391.108Skamil/// ---------------------------------------------------------------------------- 35401.108Skamil 35411.54Skamilenum bytes_transfer_type { 35421.54Skamil BYTES_TRANSFER_DATA, 35431.54Skamil BYTES_TRANSFER_DATAIO, 35441.54Skamil BYTES_TRANSFER_TEXT, 35451.54Skamil BYTES_TRANSFER_TEXTIO, 35461.54Skamil BYTES_TRANSFER_AUXV 35471.54Skamil}; 35481.31Skamil 35491.54Skamilstatic int __used 35501.54Skamilbytes_transfer_dummy(int a, int b, int c, int d) 35511.54Skamil{ 35521.54Skamil int e, f, g, h; 35531.1Skamil 35541.54Skamil a *= 4; 35551.54Skamil b += 3; 35561.54Skamil c -= 2; 35571.54Skamil d /= 1; 35581.1Skamil 35591.54Skamil e = strtol("10", NULL, 10); 35601.54Skamil f = strtol("20", NULL, 10); 35611.54Skamil g = strtol("30", NULL, 10); 35621.54Skamil h = strtol("40", NULL, 10); 35631.1Skamil 35641.54Skamil return (a + b * c - d) + (e * f - g / h); 35651.1Skamil} 35661.1Skamil 35671.54Skamilstatic void 35681.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type) 35691.1Skamil{ 35701.1Skamil const int exitval = 5; 35711.1Skamil const int sigval = SIGSTOP; 35721.1Skamil pid_t child, wpid; 35731.54Skamil bool skip = false; 35741.1Skamil 35751.54Skamil int lookup_me = 0; 35761.54Skamil uint8_t lookup_me8 = 0; 35771.54Skamil uint16_t lookup_me16 = 0; 35781.54Skamil uint32_t lookup_me32 = 0; 35791.54Skamil uint64_t lookup_me64 = 0; 35801.1Skamil 35811.54Skamil int magic = 0x13579246; 35821.54Skamil uint8_t magic8 = 0xab; 35831.54Skamil uint16_t magic16 = 0x1234; 35841.54Skamil uint32_t magic32 = 0x98765432; 35851.54Skamil uint64_t magic64 = 0xabcdef0123456789; 35861.1Skamil 35871.54Skamil struct ptrace_io_desc io; 35881.1Skamil#if defined(TWAIT_HAVE_STATUS) 35891.1Skamil int status; 35901.1Skamil#endif 35911.60Skre /* 513 is just enough, for the purposes of ATF it's good enough */ 35921.60Skre AuxInfo ai[513], *aip; 35931.55Schristos 35941.55Schristos ATF_REQUIRE(size < sizeof(ai)); 35951.1Skamil 35961.54Skamil /* Prepare variables for .TEXT transfers */ 35971.54Skamil switch (type) { 35981.54Skamil case BYTES_TRANSFER_TEXT: 35991.54Skamil memcpy(&magic, bytes_transfer_dummy, sizeof(magic)); 36001.54Skamil break; 36011.54Skamil case BYTES_TRANSFER_TEXTIO: 36021.54Skamil switch (size) { 36031.54Skamil case 8: 36041.54Skamil memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8)); 36051.54Skamil break; 36061.54Skamil case 16: 36071.54Skamil memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16)); 36081.54Skamil break; 36091.54Skamil case 32: 36101.54Skamil memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32)); 36111.54Skamil break; 36121.54Skamil case 64: 36131.54Skamil memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64)); 36141.54Skamil break; 36151.54Skamil } 36161.54Skamil break; 36171.54Skamil default: 36181.54Skamil break; 36191.54Skamil } 36201.1Skamil 36211.54Skamil /* Prepare variables for PIOD and AUXV transfers */ 36221.54Skamil switch (type) { 36231.54Skamil case BYTES_TRANSFER_TEXTIO: 36241.54Skamil case BYTES_TRANSFER_DATAIO: 36251.54Skamil io.piod_op = operation; 36261.54Skamil switch (size) { 36271.54Skamil case 8: 36281.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36291.54Skamil (void *)bytes_transfer_dummy : 36301.54Skamil &lookup_me8; 36311.54Skamil io.piod_addr = &lookup_me8; 36321.54Skamil io.piod_len = sizeof(lookup_me8); 36331.54Skamil break; 36341.54Skamil case 16: 36351.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36361.54Skamil (void *)bytes_transfer_dummy : 36371.54Skamil &lookup_me16; 36381.54Skamil io.piod_addr = &lookup_me16; 36391.54Skamil io.piod_len = sizeof(lookup_me16); 36401.54Skamil break; 36411.54Skamil case 32: 36421.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36431.54Skamil (void *)bytes_transfer_dummy : 36441.54Skamil &lookup_me32; 36451.54Skamil io.piod_addr = &lookup_me32; 36461.54Skamil io.piod_len = sizeof(lookup_me32); 36471.54Skamil break; 36481.54Skamil case 64: 36491.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 36501.54Skamil (void *)bytes_transfer_dummy : 36511.54Skamil &lookup_me64; 36521.54Skamil io.piod_addr = &lookup_me64; 36531.54Skamil io.piod_len = sizeof(lookup_me64); 36541.54Skamil break; 36551.54Skamil default: 36561.54Skamil break; 36571.54Skamil } 36581.54Skamil break; 36591.54Skamil case BYTES_TRANSFER_AUXV: 36601.54Skamil io.piod_op = operation; 36611.54Skamil io.piod_offs = 0; 36621.54Skamil io.piod_addr = ai; 36631.54Skamil io.piod_len = size; 36641.54Skamil break; 36651.54Skamil default: 36661.54Skamil break; 36671.1Skamil } 36681.1Skamil 36691.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 36701.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 36711.1Skamil if (child == 0) { 36721.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 36731.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 36741.1Skamil 36751.54Skamil switch (type) { 36761.54Skamil case BYTES_TRANSFER_DATA: 36771.54Skamil switch (operation) { 36781.54Skamil case PT_READ_D: 36791.54Skamil case PT_READ_I: 36801.54Skamil lookup_me = magic; 36811.54Skamil break; 36821.54Skamil default: 36831.54Skamil break; 36841.54Skamil } 36851.54Skamil break; 36861.54Skamil case BYTES_TRANSFER_DATAIO: 36871.54Skamil switch (operation) { 36881.54Skamil case PIOD_READ_D: 36891.54Skamil case PIOD_READ_I: 36901.54Skamil switch (size) { 36911.54Skamil case 8: 36921.54Skamil lookup_me8 = magic8; 36931.54Skamil break; 36941.54Skamil case 16: 36951.54Skamil lookup_me16 = magic16; 36961.54Skamil break; 36971.54Skamil case 32: 36981.54Skamil lookup_me32 = magic32; 36991.54Skamil break; 37001.54Skamil case 64: 37011.54Skamil lookup_me64 = magic64; 37021.54Skamil break; 37031.54Skamil default: 37041.54Skamil break; 37051.54Skamil } 37061.54Skamil break; 37071.54Skamil default: 37081.54Skamil break; 37091.54Skamil } 37101.54Skamil default: 37111.54Skamil break; 37121.54Skamil } 37131.54Skamil 37141.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 37151.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 37161.1Skamil 37171.54Skamil /* Handle PIOD and PT separately as operation values overlap */ 37181.54Skamil switch (type) { 37191.54Skamil case BYTES_TRANSFER_DATA: 37201.54Skamil switch (operation) { 37211.54Skamil case PT_WRITE_D: 37221.54Skamil case PT_WRITE_I: 37231.54Skamil FORKEE_ASSERT_EQ(lookup_me, magic); 37241.54Skamil break; 37251.54Skamil default: 37261.54Skamil break; 37271.54Skamil } 37281.54Skamil break; 37291.54Skamil case BYTES_TRANSFER_DATAIO: 37301.54Skamil switch (operation) { 37311.54Skamil case PIOD_WRITE_D: 37321.54Skamil case PIOD_WRITE_I: 37331.54Skamil switch (size) { 37341.54Skamil case 8: 37351.54Skamil FORKEE_ASSERT_EQ(lookup_me8, magic8); 37361.54Skamil break; 37371.54Skamil case 16: 37381.54Skamil FORKEE_ASSERT_EQ(lookup_me16, magic16); 37391.54Skamil break; 37401.54Skamil case 32: 37411.54Skamil FORKEE_ASSERT_EQ(lookup_me32, magic32); 37421.54Skamil break; 37431.54Skamil case 64: 37441.54Skamil FORKEE_ASSERT_EQ(lookup_me64, magic64); 37451.54Skamil break; 37461.54Skamil default: 37471.54Skamil break; 37481.54Skamil } 37491.54Skamil break; 37501.54Skamil default: 37511.54Skamil break; 37521.54Skamil } 37531.54Skamil break; 37541.54Skamil case BYTES_TRANSFER_TEXT: 37551.54Skamil FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy, 37561.54Skamil sizeof(magic)) == 0); 37571.54Skamil break; 37581.54Skamil case BYTES_TRANSFER_TEXTIO: 37591.54Skamil switch (size) { 37601.54Skamil case 8: 37611.54Skamil FORKEE_ASSERT(memcmp(&magic8, 37621.54Skamil bytes_transfer_dummy, 37631.54Skamil sizeof(magic8)) == 0); 37641.54Skamil break; 37651.54Skamil case 16: 37661.54Skamil FORKEE_ASSERT(memcmp(&magic16, 37671.54Skamil bytes_transfer_dummy, 37681.54Skamil sizeof(magic16)) == 0); 37691.54Skamil break; 37701.54Skamil case 32: 37711.54Skamil FORKEE_ASSERT(memcmp(&magic32, 37721.54Skamil bytes_transfer_dummy, 37731.54Skamil sizeof(magic32)) == 0); 37741.54Skamil break; 37751.54Skamil case 64: 37761.54Skamil FORKEE_ASSERT(memcmp(&magic64, 37771.54Skamil bytes_transfer_dummy, 37781.54Skamil sizeof(magic64)) == 0); 37791.54Skamil break; 37801.54Skamil } 37811.54Skamil break; 37821.54Skamil default: 37831.54Skamil break; 37841.54Skamil } 37851.54Skamil 37861.13Schristos DPRINTF("Before exiting of the child process\n"); 37871.1Skamil _exit(exitval); 37881.1Skamil } 37891.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 37901.1Skamil 37911.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 37921.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 37931.1Skamil 37941.1Skamil validate_status_stopped(status, sigval); 37951.1Skamil 37961.54Skamil /* Check PaX MPROTECT */ 37971.54Skamil if (!can_we_write_to_text(child)) { 37981.54Skamil switch (type) { 37991.54Skamil case BYTES_TRANSFER_TEXTIO: 38001.54Skamil switch (operation) { 38011.54Skamil case PIOD_WRITE_D: 38021.54Skamil case PIOD_WRITE_I: 38031.54Skamil skip = true; 38041.54Skamil break; 38051.54Skamil default: 38061.54Skamil break; 38071.54Skamil } 38081.54Skamil break; 38091.54Skamil case BYTES_TRANSFER_TEXT: 38101.54Skamil switch (operation) { 38111.54Skamil case PT_WRITE_D: 38121.54Skamil case PT_WRITE_I: 38131.54Skamil skip = true; 38141.54Skamil break; 38151.54Skamil default: 38161.54Skamil break; 38171.54Skamil } 38181.54Skamil break; 38191.54Skamil default: 38201.54Skamil break; 38211.54Skamil } 38221.54Skamil } 38231.1Skamil 38241.54Skamil /* Bailout cleanly killing the child process */ 38251.54Skamil if (skip) { 38261.54Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1); 38271.54Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38281.54Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 38291.54Skamil child); 38301.1Skamil 38311.54Skamil validate_status_signaled(status, SIGKILL, 0); 38321.1Skamil 38331.54Skamil atf_tc_skip("PaX MPROTECT setup prevents writes to .text"); 38341.54Skamil } 38351.1Skamil 38361.54Skamil DPRINTF("Calling operation to transfer bytes between child=%d and " 38371.54Skamil "parent=%d\n", child, getpid()); 38381.1Skamil 38391.54Skamil switch (type) { 38401.54Skamil case BYTES_TRANSFER_TEXTIO: 38411.54Skamil case BYTES_TRANSFER_DATAIO: 38421.54Skamil case BYTES_TRANSFER_AUXV: 38431.54Skamil switch (operation) { 38441.54Skamil case PIOD_WRITE_D: 38451.54Skamil case PIOD_WRITE_I: 38461.54Skamil switch (size) { 38471.54Skamil case 8: 38481.54Skamil lookup_me8 = magic8; 38491.54Skamil break; 38501.54Skamil case 16: 38511.54Skamil lookup_me16 = magic16; 38521.54Skamil break; 38531.54Skamil case 32: 38541.54Skamil lookup_me32 = magic32; 38551.54Skamil break; 38561.54Skamil case 64: 38571.54Skamil lookup_me64 = magic64; 38581.54Skamil break; 38591.54Skamil default: 38601.54Skamil break; 38611.54Skamil } 38621.54Skamil break; 38631.54Skamil default: 38641.54Skamil break; 38651.54Skamil } 38661.54Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); 38671.54Skamil switch (operation) { 38681.54Skamil case PIOD_READ_D: 38691.54Skamil case PIOD_READ_I: 38701.54Skamil switch (size) { 38711.54Skamil case 8: 38721.54Skamil ATF_REQUIRE_EQ(lookup_me8, magic8); 38731.54Skamil break; 38741.54Skamil case 16: 38751.54Skamil ATF_REQUIRE_EQ(lookup_me16, magic16); 38761.54Skamil break; 38771.54Skamil case 32: 38781.54Skamil ATF_REQUIRE_EQ(lookup_me32, magic32); 38791.54Skamil break; 38801.54Skamil case 64: 38811.54Skamil ATF_REQUIRE_EQ(lookup_me64, magic64); 38821.54Skamil break; 38831.54Skamil default: 38841.54Skamil break; 38851.54Skamil } 38861.54Skamil break; 38871.54Skamil case PIOD_READ_AUXV: 38881.54Skamil DPRINTF("Asserting that AUXV length (%zu) is > 0\n", 38891.54Skamil io.piod_len); 38901.54Skamil ATF_REQUIRE(io.piod_len > 0); 38911.54Skamil for (aip = ai; aip->a_type != AT_NULL; aip++) 38921.54Skamil DPRINTF("a_type=%#llx a_v=%#llx\n", 38931.54Skamil (long long int)aip->a_type, 38941.54Skamil (long long int)aip->a_v); 38951.54Skamil break; 38961.54Skamil default: 38971.54Skamil break; 38981.54Skamil } 38991.54Skamil break; 39001.54Skamil case BYTES_TRANSFER_TEXT: 39011.54Skamil switch (operation) { 39021.54Skamil case PT_READ_D: 39031.54Skamil case PT_READ_I: 39041.54Skamil errno = 0; 39051.54Skamil lookup_me = ptrace(operation, child, 39061.54Skamil bytes_transfer_dummy, 0); 39071.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 39081.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 39091.54Skamil break; 39101.54Skamil case PT_WRITE_D: 39111.54Skamil case PT_WRITE_I: 39121.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, 39131.54Skamil bytes_transfer_dummy, magic) 39141.54Skamil != -1); 39151.54Skamil break; 39161.54Skamil default: 39171.54Skamil break; 39181.54Skamil } 39191.54Skamil break; 39201.54Skamil case BYTES_TRANSFER_DATA: 39211.54Skamil switch (operation) { 39221.54Skamil case PT_READ_D: 39231.54Skamil case PT_READ_I: 39241.54Skamil errno = 0; 39251.54Skamil lookup_me = ptrace(operation, child, &lookup_me, 0); 39261.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 39271.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 39281.54Skamil break; 39291.54Skamil case PT_WRITE_D: 39301.54Skamil case PT_WRITE_I: 39311.54Skamil lookup_me = magic; 39321.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me, 39331.54Skamil magic) != -1); 39341.54Skamil break; 39351.54Skamil default: 39361.54Skamil break; 39371.54Skamil } 39381.54Skamil break; 39391.54Skamil default: 39401.54Skamil break; 39411.54Skamil } 39421.1Skamil 39431.13Schristos DPRINTF("Before resuming the child process where it left off and " 39441.1Skamil "without signal to be sent\n"); 39451.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 39461.1Skamil 39471.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39481.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 39491.1Skamil 39501.1Skamil validate_status_exited(status, exitval); 39511.1Skamil 39521.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39531.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 39541.1Skamil} 39551.1Skamil 39561.61Skre#define BYTES_TRANSFER(test, operation, size, type) \ 39571.61SkreATF_TC(test); \ 39581.61SkreATF_TC_HEAD(test, tc) \ 39591.61Skre{ \ 39601.61Skre atf_tc_set_md_var(tc, "descr", \ 39611.61Skre "Verify bytes transfer operation" #operation " and size " #size \ 39621.61Skre " of type " #type); \ 39631.61Skre} \ 39641.61Skre \ 39651.61SkreATF_TC_BODY(test, tc) \ 39661.61Skre{ \ 39671.61Skre \ 39681.61Skre bytes_transfer(operation, size, BYTES_TRANSFER_##type); \ 39691.1Skamil} 39701.1Skamil 39711.54Skamil// DATA 39721.1Skamil 39731.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO) 39741.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO) 39751.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO) 39761.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO) 39771.54Skamil 39781.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO) 39791.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO) 39801.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO) 39811.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO) 39821.54Skamil 39831.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO) 39841.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO) 39851.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO) 39861.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO) 39871.54Skamil 39881.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO) 39891.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO) 39901.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO) 39911.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO) 39921.54Skamil 39931.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA) 39941.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA) 39951.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA) 39961.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA) 39971.54Skamil 39981.54Skamil// TEXT 39991.54Skamil 40001.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO) 40011.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO) 40021.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO) 40031.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO) 40041.54Skamil 40051.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO) 40061.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO) 40071.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO) 40081.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO) 40091.54Skamil 40101.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO) 40111.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO) 40121.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO) 40131.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO) 40141.54Skamil 40151.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO) 40161.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO) 40171.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO) 40181.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO) 40191.54Skamil 40201.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT) 40211.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT) 40221.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT) 40231.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT) 40241.1Skamil 40251.54Skamil// AUXV 40261.1Skamil 40271.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV) 40281.1Skamil 40291.54Skamil/// ---------------------------------------------------------------------------- 40301.1Skamil 40311.101Skamilstatic void 40321.101Skamilbytes_transfer_alignment(const char *operation) 40331.101Skamil{ 40341.101Skamil const int exitval = 5; 40351.101Skamil const int sigval = SIGSTOP; 40361.101Skamil pid_t child, wpid; 40371.101Skamil#if defined(TWAIT_HAVE_STATUS) 40381.101Skamil int status; 40391.101Skamil#endif 40401.101Skamil char *buffer; 40411.101Skamil int vector; 40421.101Skamil size_t len; 40431.101Skamil size_t i; 40441.101Skamil int op; 40451.101Skamil 40461.101Skamil struct ptrace_io_desc io; 40471.101Skamil struct ptrace_siginfo info; 40481.101Skamil 40491.101Skamil memset(&io, 0, sizeof(io)); 40501.101Skamil memset(&info, 0, sizeof(info)); 40511.101Skamil 40521.101Skamil /* Testing misaligned byte transfer crossing page boundaries */ 40531.101Skamil len = sysconf(_SC_PAGESIZE) * 2; 40541.101Skamil buffer = malloc(len); 40551.101Skamil ATF_REQUIRE(buffer != NULL); 40561.101Skamil 40571.101Skamil /* Initialize the buffer with random data */ 40581.101Skamil for (i = 0; i < len; i++) 40591.101Skamil buffer[i] = i & 0xff; 40601.101Skamil 40611.101Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 40621.101Skamil SYSCALL_REQUIRE((child = fork()) != -1); 40631.101Skamil if (child == 0) { 40641.101Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 40651.101Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 40661.101Skamil 40671.101Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 40681.101Skamil FORKEE_ASSERT(raise(sigval) == 0); 40691.101Skamil 40701.101Skamil DPRINTF("Before exiting of the child process\n"); 40711.101Skamil _exit(exitval); 40721.101Skamil } 40731.101Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 40741.101Skamil 40751.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 40761.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 40771.101Skamil 40781.101Skamil validate_status_stopped(status, sigval); 40791.101Skamil 40801.101Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 40811.101Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 40821.101Skamil != -1); 40831.101Skamil 40841.101Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 40851.101Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 40861.101Skamil "si_errno=%#x\n", 40871.101Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 40881.101Skamil info.psi_siginfo.si_errno); 40891.101Skamil 40901.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 40911.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 40921.101Skamil 40931.101Skamil if (strcmp(operation, "PT_READ_I") == 0 || 40941.101Skamil strcmp(operation, "PT_READ_D") == 0) { 40951.101Skamil if (strcmp(operation, "PT_READ_I")) 40961.101Skamil op = PT_READ_I; 40971.101Skamil else 40981.101Skamil op = PT_READ_D; 40991.101Skamil 41001.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41011.101Skamil errno = 0; 41021.101Skamil vector = ptrace(op, child, buffer + i, 0); 41031.101Skamil ATF_REQUIRE_EQ(errno, 0); 41041.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 41051.101Skamil } 41061.101Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 41071.101Skamil strcmp(operation, "PT_WRITE_D") == 0) { 41081.101Skamil if (strcmp(operation, "PT_WRITE_I")) 41091.101Skamil op = PT_WRITE_I; 41101.101Skamil else 41111.101Skamil op = PT_WRITE_D; 41121.101Skamil 41131.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41141.101Skamil memcpy(&vector, buffer + i, sizeof(int)); 41151.101Skamil SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector) 41161.101Skamil != -1); 41171.101Skamil } 41181.101Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 41191.101Skamil strcmp(operation, "PIOD_READ_D") == 0) { 41201.101Skamil if (strcmp(operation, "PIOD_READ_I")) 41211.101Skamil op = PIOD_READ_I; 41221.101Skamil else 41231.101Skamil op = PIOD_READ_D; 41241.101Skamil 41251.101Skamil io.piod_op = op; 41261.101Skamil io.piod_addr = &vector; 41271.101Skamil io.piod_len = sizeof(int); 41281.101Skamil 41291.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41301.101Skamil io.piod_offs = buffer + i; 41311.101Skamil 41321.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41331.101Skamil != -1); 41341.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 41351.101Skamil } 41361.101Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 41371.101Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 41381.101Skamil if (strcmp(operation, "PIOD_WRITE_I")) 41391.101Skamil op = PIOD_WRITE_I; 41401.101Skamil else 41411.101Skamil op = PIOD_WRITE_D; 41421.101Skamil 41431.101Skamil io.piod_op = op; 41441.101Skamil io.piod_addr = &vector; 41451.101Skamil io.piod_len = sizeof(int); 41461.101Skamil 41471.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 41481.101Skamil io.piod_offs = buffer + i; 41491.101Skamil 41501.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41511.101Skamil != -1); 41521.101Skamil } 41531.101Skamil } else if (strcmp(operation, "PIOD_READ_AUXV") == 0) { 41541.101Skamil io.piod_op = PIOD_READ_AUXV; 41551.101Skamil io.piod_addr = &vector; 41561.101Skamil io.piod_len = sizeof(int); 41571.101Skamil 41581.101Skamil errno = 0; 41591.101Skamil i = 0; 41601.101Skamil /* Read the whole AUXV vector, it has no clear length */ 41611.120Skamil while (io.piod_len > 0) { 41621.101Skamil io.piod_offs = (void *)(intptr_t)i; 41631.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 41641.120Skamil != -1 || (io.piod_len == 0 && i > 0)); 41651.101Skamil ++i; 41661.101Skamil } 41671.101Skamil } 41681.101Skamil 41691.101Skamil DPRINTF("Before resuming the child process where it left off " 41701.101Skamil "and without signal to be sent\n"); 41711.101Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 41721.101Skamil 41731.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41741.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 41751.101Skamil child); 41761.101Skamil 41771.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41781.101Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 41791.101Skamil} 41801.101Skamil 41811.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation) \ 41821.101SkamilATF_TC(test); \ 41831.101SkamilATF_TC_HEAD(test, tc) \ 41841.101Skamil{ \ 41851.101Skamil atf_tc_set_md_var(tc, "descr", \ 41861.101Skamil "Verify bytes transfer for potentially misaligned " \ 41871.101Skamil "operation " operation); \ 41881.101Skamil} \ 41891.101Skamil \ 41901.101SkamilATF_TC_BODY(test, tc) \ 41911.101Skamil{ \ 41921.101Skamil \ 41931.101Skamil bytes_transfer_alignment(operation); \ 41941.101Skamil} 41951.101Skamil 41961.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I") 41971.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D") 41981.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I") 41991.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D") 42001.101Skamil 42011.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I") 42021.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D") 42031.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I") 42041.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D") 42051.101Skamil 42061.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV") 42071.101Skamil 42081.101Skamil/// ---------------------------------------------------------------------------- 42091.101Skamil 42101.115Skamilstatic void 42111.115Skamilbytes_transfer_eof(const char *operation) 42121.115Skamil{ 42131.115Skamil const int exitval = 5; 42141.115Skamil const int sigval = SIGSTOP; 42151.115Skamil pid_t child, wpid; 42161.115Skamil#if defined(TWAIT_HAVE_STATUS) 42171.115Skamil int status; 42181.115Skamil#endif 42191.115Skamil FILE *fp; 42201.115Skamil char *p; 42211.115Skamil int vector; 42221.115Skamil int op; 42231.115Skamil 42241.115Skamil struct ptrace_io_desc io; 42251.115Skamil struct ptrace_siginfo info; 42261.115Skamil 42271.115Skamil memset(&io, 0, sizeof(io)); 42281.115Skamil memset(&info, 0, sizeof(info)); 42291.115Skamil 42301.115Skamil vector = 0; 42311.115Skamil 42321.115Skamil fp = tmpfile(); 42331.115Skamil ATF_REQUIRE(fp != NULL); 42341.115Skamil 42351.115Skamil p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0); 42361.115Skamil ATF_REQUIRE(p != MAP_FAILED); 42371.115Skamil 42381.115Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 42391.115Skamil SYSCALL_REQUIRE((child = fork()) != -1); 42401.115Skamil if (child == 0) { 42411.115Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 42421.115Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 42431.115Skamil 42441.115Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 42451.115Skamil FORKEE_ASSERT(raise(sigval) == 0); 42461.115Skamil 42471.115Skamil DPRINTF("Before exiting of the child process\n"); 42481.115Skamil _exit(exitval); 42491.115Skamil } 42501.115Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 42511.115Skamil 42521.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 42531.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 42541.115Skamil 42551.115Skamil validate_status_stopped(status, sigval); 42561.115Skamil 42571.115Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 42581.115Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 42591.115Skamil != -1); 42601.115Skamil 42611.115Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 42621.115Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 42631.115Skamil "si_errno=%#x\n", 42641.115Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 42651.115Skamil info.psi_siginfo.si_errno); 42661.115Skamil 42671.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 42681.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 42691.115Skamil 42701.115Skamil if (strcmp(operation, "PT_READ_I") == 0 || 42711.115Skamil strcmp(operation, "PT_READ_D") == 0) { 42721.115Skamil if (strcmp(operation, "PT_READ_I")) 42731.115Skamil op = PT_READ_I; 42741.115Skamil else 42751.115Skamil op = PT_READ_D; 42761.115Skamil 42771.115Skamil errno = 0; 42781.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, 0) == -1); 42791.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 42801.115Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 42811.115Skamil strcmp(operation, "PT_WRITE_D") == 0) { 42821.115Skamil if (strcmp(operation, "PT_WRITE_I")) 42831.115Skamil op = PT_WRITE_I; 42841.115Skamil else 42851.115Skamil op = PT_WRITE_D; 42861.115Skamil 42871.115Skamil errno = 0; 42881.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, vector) == -1); 42891.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 42901.115Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 42911.115Skamil strcmp(operation, "PIOD_READ_D") == 0) { 42921.115Skamil if (strcmp(operation, "PIOD_READ_I")) 42931.115Skamil op = PIOD_READ_I; 42941.115Skamil else 42951.115Skamil op = PIOD_READ_D; 42961.115Skamil 42971.115Skamil io.piod_op = op; 42981.115Skamil io.piod_addr = &vector; 42991.115Skamil io.piod_len = sizeof(int); 43001.115Skamil io.piod_offs = p; 43011.115Skamil 43021.115Skamil errno = 0; 43031.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 43041.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43051.115Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 43061.115Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 43071.115Skamil if (strcmp(operation, "PIOD_WRITE_I")) 43081.115Skamil op = PIOD_WRITE_I; 43091.115Skamil else 43101.115Skamil op = PIOD_WRITE_D; 43111.115Skamil 43121.115Skamil io.piod_op = op; 43131.115Skamil io.piod_addr = &vector; 43141.115Skamil io.piod_len = sizeof(int); 43151.115Skamil io.piod_offs = p; 43161.115Skamil 43171.115Skamil errno = 0; 43181.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 43191.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 43201.115Skamil } 43211.115Skamil 43221.115Skamil DPRINTF("Before resuming the child process where it left off " 43231.115Skamil "and without signal to be sent\n"); 43241.115Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 43251.115Skamil 43261.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43271.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 43281.115Skamil child); 43291.115Skamil 43301.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43311.115Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 43321.115Skamil} 43331.115Skamil 43341.115Skamil#define BYTES_TRANSFER_EOF(test, operation) \ 43351.115SkamilATF_TC(test); \ 43361.115SkamilATF_TC_HEAD(test, tc) \ 43371.115Skamil{ \ 43381.115Skamil atf_tc_set_md_var(tc, "descr", \ 43391.115Skamil "Verify bytes EOF byte transfer for the " operation \ 43401.115Skamil " operation"); \ 43411.115Skamil} \ 43421.115Skamil \ 43431.115SkamilATF_TC_BODY(test, tc) \ 43441.115Skamil{ \ 43451.115Skamil \ 43461.115Skamil bytes_transfer_eof(operation); \ 43471.115Skamil} 43481.115Skamil 43491.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_i, "PT_READ_I") 43501.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_d, "PT_READ_D") 43511.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_i, "PT_WRITE_I") 43521.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_d, "PT_WRITE_D") 43531.115Skamil 43541.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_i, "PIOD_READ_I") 43551.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_d, "PIOD_READ_D") 43561.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_i, "PIOD_WRITE_I") 43571.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_d, "PIOD_WRITE_D") 43581.115Skamil 43591.115Skamil/// ---------------------------------------------------------------------------- 43601.115Skamil 43611.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS) 43621.72Skamilstatic void 43631.72Skamilaccess_regs(const char *regset, const char *aux) 43641.1Skamil{ 43651.1Skamil const int exitval = 5; 43661.1Skamil const int sigval = SIGSTOP; 43671.1Skamil pid_t child, wpid; 43681.1Skamil#if defined(TWAIT_HAVE_STATUS) 43691.1Skamil int status; 43701.1Skamil#endif 43711.72Skamil#if defined(HAVE_GPREGS) 43721.72Skamil struct reg gpr; 43731.76Sscole register_t rgstr; 43741.1Skamil#endif 43751.72Skamil#if defined(HAVE_FPREGS) 43761.72Skamil struct fpreg fpr; 43771.1Skamil#endif 43781.76Sscole 43791.72Skamil#if !defined(HAVE_GPREGS) 43801.72Skamil if (strcmp(regset, "regs") == 0) 43811.72Skamil atf_tc_fail("Impossible test scenario!"); 43821.1Skamil#endif 43831.1Skamil 43841.72Skamil#if !defined(HAVE_FPREGS) 43851.72Skamil if (strcmp(regset, "fpregs") == 0) 43861.72Skamil atf_tc_fail("Impossible test scenario!"); 43871.1Skamil#endif 43881.1Skamil 43891.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 43901.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 43911.1Skamil if (child == 0) { 43921.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 43931.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 43941.1Skamil 43951.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 43961.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 43971.1Skamil 43981.13Schristos DPRINTF("Before exiting of the child process\n"); 43991.1Skamil _exit(exitval); 44001.1Skamil } 44011.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 44021.1Skamil 44031.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44041.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44051.1Skamil 44061.1Skamil validate_status_stopped(status, sigval); 44071.1Skamil 44081.1Skamil#if defined(HAVE_GPREGS) 44091.72Skamil if (strcmp(regset, "regs") == 0) { 44101.72Skamil DPRINTF("Call GETREGS for the child process\n"); 44111.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1); 44121.72Skamil 44131.72Skamil if (strcmp(aux, "none") == 0) { 44141.72Skamil DPRINTF("Retrieved registers\n"); 44151.72Skamil } else if (strcmp(aux, "pc") == 0) { 44161.72Skamil rgstr = PTRACE_REG_PC(&gpr); 44171.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44181.72Skamil } else if (strcmp(aux, "set_pc") == 0) { 44191.72Skamil rgstr = PTRACE_REG_PC(&gpr); 44201.72Skamil PTRACE_REG_SET_PC(&gpr, rgstr); 44211.72Skamil } else if (strcmp(aux, "sp") == 0) { 44221.72Skamil rgstr = PTRACE_REG_SP(&gpr); 44231.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44241.72Skamil } else if (strcmp(aux, "intrv") == 0) { 44251.72Skamil rgstr = PTRACE_REG_INTRV(&gpr); 44261.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 44271.72Skamil } else if (strcmp(aux, "setregs") == 0) { 44281.72Skamil DPRINTF("Call SETREGS for the child process\n"); 44291.72Skamil SYSCALL_REQUIRE( 44301.72Skamil ptrace(PT_GETREGS, child, &gpr, 0) != -1); 44311.72Skamil } 44321.72Skamil } 44331.1Skamil#endif 44341.1Skamil 44351.72Skamil#if defined(HAVE_FPREGS) 44361.72Skamil if (strcmp(regset, "fpregs") == 0) { 44371.72Skamil DPRINTF("Call GETFPREGS for the child process\n"); 44381.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1); 44391.72Skamil 44401.72Skamil if (strcmp(aux, "getfpregs") == 0) { 44411.72Skamil DPRINTF("Retrieved FP registers\n"); 44421.72Skamil } else if (strcmp(aux, "setfpregs") == 0) { 44431.72Skamil DPRINTF("Call SETFPREGS for the child\n"); 44441.72Skamil SYSCALL_REQUIRE( 44451.72Skamil ptrace(PT_SETFPREGS, child, &fpr, 0) != -1); 44461.72Skamil } 44471.1Skamil } 44481.1Skamil#endif 44491.1Skamil 44501.13Schristos DPRINTF("Before resuming the child process where it left off and " 44511.1Skamil "without signal to be sent\n"); 44521.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 44531.1Skamil 44541.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44551.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44561.1Skamil 44571.1Skamil validate_status_exited(status, exitval); 44581.1Skamil 44591.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44601.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 44611.1Skamil} 44621.1Skamil 44631.72Skamil#define ACCESS_REGS(test, regset, aux) \ 44641.72SkamilATF_TC(test); \ 44651.72SkamilATF_TC_HEAD(test, tc) \ 44661.72Skamil{ \ 44671.72Skamil atf_tc_set_md_var(tc, "descr", \ 44681.72Skamil "Verify " regset " with auxiliary operation: " aux); \ 44691.72Skamil} \ 44701.72Skamil \ 44711.72SkamilATF_TC_BODY(test, tc) \ 44721.72Skamil{ \ 44731.72Skamil \ 44741.72Skamil access_regs(regset, aux); \ 44751.1Skamil} 44761.1Skamil#endif 44771.1Skamil 44781.72Skamil#if defined(HAVE_GPREGS) 44791.72SkamilACCESS_REGS(access_regs1, "regs", "none") 44801.72SkamilACCESS_REGS(access_regs2, "regs", "pc") 44811.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc") 44821.72SkamilACCESS_REGS(access_regs4, "regs", "sp") 44831.72SkamilACCESS_REGS(access_regs5, "regs", "intrv") 44841.72SkamilACCESS_REGS(access_regs6, "regs", "setregs") 44851.1Skamil#endif 44861.1Skamil#if defined(HAVE_FPREGS) 44871.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs") 44881.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs") 44891.1Skamil#endif 44901.1Skamil 44911.72Skamil/// ---------------------------------------------------------------------------- 44921.1Skamil 44931.1Skamil#if defined(PT_STEP) 44941.1Skamilstatic void 44951.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored) 44961.1Skamil{ 44971.1Skamil const int exitval = 5; 44981.1Skamil const int sigval = SIGSTOP; 44991.1Skamil pid_t child, wpid; 45001.1Skamil#if defined(TWAIT_HAVE_STATUS) 45011.1Skamil int status; 45021.1Skamil#endif 45031.1Skamil int happy; 45041.95Skamil struct sigaction sa; 45051.81Skamil struct ptrace_siginfo info; 45061.95Skamil sigset_t intmask; 45071.95Skamil struct kinfo_proc2 kp; 45081.95Skamil size_t len = sizeof(kp); 45091.95Skamil 45101.95Skamil int name[6]; 45111.95Skamil const size_t namelen = __arraycount(name); 45121.95Skamil ki_sigset_t kp_sigmask; 45131.95Skamil ki_sigset_t kp_sigignore; 45141.1Skamil 45151.1Skamil#if defined(__arm__) 45161.1Skamil /* PT_STEP not supported on arm 32-bit */ 45171.1Skamil atf_tc_expect_fail("PR kern/52119"); 45181.1Skamil#endif 45191.1Skamil 45201.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 45211.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 45221.1Skamil if (child == 0) { 45231.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 45241.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 45251.1Skamil 45261.95Skamil if (masked) { 45271.95Skamil sigemptyset(&intmask); 45281.95Skamil sigaddset(&intmask, SIGTRAP); 45291.95Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 45301.95Skamil } 45311.95Skamil 45321.95Skamil if (ignored) { 45331.95Skamil memset(&sa, 0, sizeof(sa)); 45341.95Skamil sa.sa_handler = SIG_IGN; 45351.95Skamil sigemptyset(&sa.sa_mask); 45361.95Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 45371.95Skamil } 45381.95Skamil 45391.1Skamil happy = check_happy(999); 45401.1Skamil 45411.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 45421.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 45431.1Skamil 45441.1Skamil FORKEE_ASSERT_EQ(happy, check_happy(999)); 45451.1Skamil 45461.13Schristos DPRINTF("Before exiting of the child process\n"); 45471.1Skamil _exit(exitval); 45481.1Skamil } 45491.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 45501.1Skamil 45511.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45521.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 45531.1Skamil 45541.1Skamil validate_status_stopped(status, sigval); 45551.1Skamil 45561.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 45571.81Skamil SYSCALL_REQUIRE( 45581.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 45591.81Skamil 45601.81Skamil DPRINTF("Before checking siginfo_t\n"); 45611.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 45621.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 45631.81Skamil 45641.95Skamil name[0] = CTL_KERN, 45651.95Skamil name[1] = KERN_PROC2, 45661.95Skamil name[2] = KERN_PROC_PID; 45671.95Skamil name[3] = child; 45681.95Skamil name[4] = sizeof(kp); 45691.95Skamil name[5] = 1; 45701.95Skamil 45711.95Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 45721.95Skamil 45731.95Skamil if (masked) 45741.95Skamil kp_sigmask = kp.p_sigmask; 45751.95Skamil 45761.95Skamil if (ignored) 45771.95Skamil kp_sigignore = kp.p_sigignore; 45781.95Skamil 45791.1Skamil while (N --> 0) { 45801.2Skamil if (setstep) { 45811.13Schristos DPRINTF("Before resuming the child process where it " 45821.2Skamil "left off and without signal to be sent (use " 45831.9Skamil "PT_SETSTEP and PT_CONTINUE)\n"); 45841.13Schristos SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1); 45851.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) 45861.2Skamil != -1); 45871.2Skamil } else { 45881.13Schristos DPRINTF("Before resuming the child process where it " 45891.2Skamil "left off and without signal to be sent (use " 45901.2Skamil "PT_STEP)\n"); 45911.13Schristos SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) 45921.2Skamil != -1); 45931.2Skamil } 45941.1Skamil 45951.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45961.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 45971.1Skamil child); 45981.1Skamil 45991.1Skamil validate_status_stopped(status, SIGTRAP); 46001.2Skamil 46011.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 46021.81Skamil SYSCALL_REQUIRE( 46031.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 46041.81Skamil 46051.81Skamil DPRINTF("Before checking siginfo_t\n"); 46061.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 46071.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE); 46081.81Skamil 46091.2Skamil if (setstep) { 46101.13Schristos SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1); 46111.2Skamil } 46121.95Skamil 46131.95Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 46141.95Skamil 46151.95Skamil if (masked) { 46161.95Skamil DPRINTF("kp_sigmask=" 46171.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46181.95Skamil PRIx32 "\n", 46191.95Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 46201.95Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 46211.95Skamil 46221.95Skamil DPRINTF("kp.p_sigmask=" 46231.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46241.95Skamil PRIx32 "\n", 46251.95Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 46261.95Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 46271.95Skamil 46281.95Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 46291.95Skamil sizeof(kp_sigmask))); 46301.95Skamil } 46311.95Skamil 46321.95Skamil if (ignored) { 46331.95Skamil DPRINTF("kp_sigignore=" 46341.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46351.95Skamil PRIx32 "\n", 46361.95Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 46371.95Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 46381.95Skamil 46391.95Skamil DPRINTF("kp.p_sigignore=" 46401.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 46411.95Skamil PRIx32 "\n", 46421.95Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 46431.95Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 46441.95Skamil 46451.95Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 46461.95Skamil sizeof(kp_sigignore))); 46471.95Skamil } 46481.1Skamil } 46491.1Skamil 46501.13Schristos DPRINTF("Before resuming the child process where it left off and " 46511.1Skamil "without signal to be sent\n"); 46521.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 46531.1Skamil 46541.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46551.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 46561.1Skamil 46571.1Skamil validate_status_exited(status, exitval); 46581.1Skamil 46591.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46601.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 46611.1Skamil} 46621.1Skamil 46631.73Skamil#define PTRACE_STEP(test, N, setstep) \ 46641.73SkamilATF_TC(test); \ 46651.73SkamilATF_TC_HEAD(test, tc) \ 46661.73Skamil{ \ 46671.73Skamil atf_tc_set_md_var(tc, "descr", \ 46681.74Skamil "Verify " #N " (PT_SETSTEP set to: " #setstep ")"); \ 46691.73Skamil} \ 46701.73Skamil \ 46711.73SkamilATF_TC_BODY(test, tc) \ 46721.73Skamil{ \ 46731.73Skamil \ 46741.95Skamil ptrace_step(N, setstep, false, false); \ 46751.1Skamil} 46761.1Skamil 46771.73SkamilPTRACE_STEP(step1, 1, 0) 46781.73SkamilPTRACE_STEP(step2, 2, 0) 46791.73SkamilPTRACE_STEP(step3, 3, 0) 46801.73SkamilPTRACE_STEP(step4, 4, 0) 46811.73SkamilPTRACE_STEP(setstep1, 1, 1) 46821.73SkamilPTRACE_STEP(setstep2, 2, 1) 46831.73SkamilPTRACE_STEP(setstep3, 3, 1) 46841.73SkamilPTRACE_STEP(setstep4, 4, 1) 46851.95Skamil 46861.95SkamilATF_TC(step_signalmasked); 46871.95SkamilATF_TC_HEAD(step_signalmasked, tc) 46881.95Skamil{ 46891.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP"); 46901.95Skamil} 46911.95Skamil 46921.95SkamilATF_TC_BODY(step_signalmasked, tc) 46931.95Skamil{ 46941.95Skamil 46951.95Skamil ptrace_step(1, 0, true, false); 46961.95Skamil} 46971.95Skamil 46981.95SkamilATF_TC(step_signalignored); 46991.95SkamilATF_TC_HEAD(step_signalignored, tc) 47001.95Skamil{ 47011.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP"); 47021.95Skamil} 47031.95Skamil 47041.95SkamilATF_TC_BODY(step_signalignored, tc) 47051.95Skamil{ 47061.95Skamil 47071.95Skamil ptrace_step(1, 0, false, true); 47081.95Skamil} 47091.1Skamil#endif 47101.1Skamil 47111.73Skamil/// ---------------------------------------------------------------------------- 47121.1Skamil 47131.75Skamilstatic void 47141.75Skamilptrace_kill(const char *type) 47151.1Skamil{ 47161.75Skamil const int sigval = SIGSTOP; 47171.1Skamil pid_t child, wpid; 47181.1Skamil#if defined(TWAIT_HAVE_STATUS) 47191.1Skamil int status; 47201.1Skamil#endif 47211.1Skamil 47221.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 47231.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 47241.1Skamil if (child == 0) { 47251.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 47261.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 47271.1Skamil 47281.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 47291.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 47301.1Skamil 47311.1Skamil /* NOTREACHED */ 47321.1Skamil FORKEE_ASSERTX(0 && 47331.1Skamil "Child should be terminated by a signal from its parent"); 47341.1Skamil } 47351.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 47361.1Skamil 47371.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47381.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47391.1Skamil 47401.1Skamil validate_status_stopped(status, sigval); 47411.1Skamil 47421.75Skamil DPRINTF("Before killing the child process with %s\n", type); 47431.75Skamil if (strcmp(type, "ptrace(PT_KILL)") == 0) { 47441.75Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1); 47451.75Skamil } else if (strcmp(type, "kill(SIGKILL)") == 0) { 47461.75Skamil kill(child, SIGKILL); 47471.75Skamil } else if (strcmp(type, "killpg(SIGKILL)") == 0) { 47481.75Skamil setpgid(child, 0); 47491.75Skamil killpg(getpgid(child), SIGKILL); 47501.75Skamil } 47511.1Skamil 47521.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47531.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47541.1Skamil 47551.75Skamil validate_status_signaled(status, SIGKILL, 0); 47561.1Skamil 47571.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47581.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 47591.1Skamil} 47601.1Skamil 47611.75Skamil#define PTRACE_KILL(test, type) \ 47621.75SkamilATF_TC(test); \ 47631.75SkamilATF_TC_HEAD(test, tc) \ 47641.75Skamil{ \ 47651.75Skamil atf_tc_set_md_var(tc, "descr", \ 47661.75Skamil "Verify killing the child with " type); \ 47671.75Skamil} \ 47681.75Skamil \ 47691.75SkamilATF_TC_BODY(test, tc) \ 47701.75Skamil{ \ 47711.75Skamil \ 47721.75Skamil ptrace_kill(type); \ 47731.1Skamil} 47741.1Skamil 47751.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1 47761.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)") 47771.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)") 47781.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)") 47791.1Skamil 47801.75Skamil/// ---------------------------------------------------------------------------- 47811.1Skamil 47821.77Skamilstatic void 47831.77Skamiltraceme_lwpinfo(const int threads) 47841.1Skamil{ 47851.1Skamil const int sigval = SIGSTOP; 47861.77Skamil const int sigval2 = SIGINT; 47871.1Skamil pid_t child, wpid; 47881.1Skamil#if defined(TWAIT_HAVE_STATUS) 47891.1Skamil int status; 47901.1Skamil#endif 47911.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 47921.77Skamil struct ptrace_siginfo info; 47931.77Skamil 47941.77Skamil /* Maximum number of supported threads in this test */ 47951.77Skamil pthread_t t[3]; 47961.77Skamil int n, rv; 47971.77Skamil 47981.77Skamil ATF_REQUIRE((int)__arraycount(t) >= threads); 47991.1Skamil 48001.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 48011.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 48021.1Skamil if (child == 0) { 48031.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 48041.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 48051.1Skamil 48061.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 48071.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 48081.1Skamil 48091.77Skamil for (n = 0; n < threads; n++) { 48101.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 48111.77Skamil FORKEE_ASSERT(rv == 0); 48121.77Skamil } 48131.77Skamil 48141.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval2)); 48151.77Skamil FORKEE_ASSERT(raise(sigval2) == 0); 48161.77Skamil 48171.77Skamil /* NOTREACHED */ 48181.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 48191.1Skamil } 48201.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 48211.1Skamil 48221.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48231.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48241.1Skamil 48251.1Skamil validate_status_stopped(status, sigval); 48261.1Skamil 48271.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 48281.77Skamil SYSCALL_REQUIRE( 48291.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 48301.77Skamil 48311.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 48321.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 48331.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 48341.77Skamil info.psi_siginfo.si_errno); 48351.77Skamil 48361.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 48371.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 48381.77Skamil 48391.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48401.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48411.1Skamil 48421.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 48431.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 48441.1Skamil 48451.13Schristos DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n", 48461.77Skamil lwp.pl_lwpid); 48471.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 48481.1Skamil 48491.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48501.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48511.1Skamil 48521.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 48531.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 48541.1Skamil 48551.13Schristos DPRINTF("Before resuming the child process where it left off and " 48561.1Skamil "without signal to be sent\n"); 48571.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 48581.1Skamil 48591.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48601.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48611.1Skamil 48621.77Skamil validate_status_stopped(status, sigval2); 48631.77Skamil 48641.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 48651.77Skamil SYSCALL_REQUIRE( 48661.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 48671.77Skamil 48681.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 48691.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 48701.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 48711.77Skamil info.psi_siginfo.si_errno); 48721.77Skamil 48731.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2); 48741.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 48751.77Skamil 48761.77Skamil memset(&lwp, 0, sizeof(lwp)); 48771.77Skamil 48781.77Skamil for (n = 0; n <= threads; n++) { 48791.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48801.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48811.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 48821.77Skamil 48831.77Skamil DPRINTF("Assert that the thread exists\n"); 48841.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 48851.77Skamil 48861.77Skamil DPRINTF("Assert that lwp thread %d received expected event\n", 48871.77Skamil lwp.pl_lwpid); 48881.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ? 48891.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 48901.77Skamil } 48911.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48921.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48931.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 48941.77Skamil 48951.77Skamil DPRINTF("Assert that there are no more threads\n"); 48961.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 48971.77Skamil 48981.77Skamil DPRINTF("Before resuming the child process where it left off and " 48991.77Skamil "without signal to be sent\n"); 49001.77Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1); 49011.77Skamil 49021.77Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49031.77Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 49041.77Skamil 49051.77Skamil validate_status_signaled(status, SIGKILL, 0); 49061.1Skamil 49071.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49081.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 49091.1Skamil} 49101.1Skamil 49111.77Skamil#define TRACEME_LWPINFO(test, threads) \ 49121.77SkamilATF_TC(test); \ 49131.77SkamilATF_TC_HEAD(test, tc) \ 49141.77Skamil{ \ 49151.77Skamil atf_tc_set_md_var(tc, "descr", \ 49161.77Skamil "Verify LWPINFO with the child with " #threads \ 49171.77Skamil " spawned extra threads"); \ 49181.77Skamil} \ 49191.77Skamil \ 49201.77SkamilATF_TC_BODY(test, tc) \ 49211.77Skamil{ \ 49221.77Skamil \ 49231.77Skamil traceme_lwpinfo(threads); \ 49241.1Skamil} 49251.1Skamil 49261.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0) 49271.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1) 49281.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2) 49291.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3) 49301.77Skamil 49311.77Skamil/// ---------------------------------------------------------------------------- 49321.77Skamil 49331.77Skamil#if defined(TWAIT_HAVE_PID) 49341.77Skamilstatic void 49351.77Skamilattach_lwpinfo(const int threads) 49361.1Skamil{ 49371.77Skamil const int sigval = SIGINT; 49381.1Skamil struct msg_fds parent_tracee, parent_tracer; 49391.1Skamil const int exitval_tracer = 10; 49401.1Skamil pid_t tracee, tracer, wpid; 49411.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 49421.1Skamil#if defined(TWAIT_HAVE_STATUS) 49431.1Skamil int status; 49441.1Skamil#endif 49451.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 49461.77Skamil struct ptrace_siginfo info; 49471.77Skamil 49481.77Skamil /* Maximum number of supported threads in this test */ 49491.77Skamil pthread_t t[3]; 49501.77Skamil int n, rv; 49511.1Skamil 49521.13Schristos DPRINTF("Spawn tracee\n"); 49531.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 49541.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 49551.1Skamil tracee = atf_utils_fork(); 49561.1Skamil if (tracee == 0) { 49571.1Skamil /* Wait for message from the parent */ 49581.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 49591.1Skamil 49601.77Skamil CHILD_FROM_PARENT("spawn threads", parent_tracee, msg); 49611.77Skamil 49621.77Skamil for (n = 0; n < threads; n++) { 49631.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 49641.77Skamil FORKEE_ASSERT(rv == 0); 49651.77Skamil } 49661.77Skamil 49671.77Skamil CHILD_TO_PARENT("tracee exit", parent_tracee, msg); 49681.77Skamil 49691.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 49701.77Skamil FORKEE_ASSERT(raise(sigval) == 0); 49711.77Skamil 49721.77Skamil /* NOTREACHED */ 49731.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 49741.1Skamil } 49751.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 49761.1Skamil 49771.13Schristos DPRINTF("Spawn debugger\n"); 49781.1Skamil tracer = atf_utils_fork(); 49791.1Skamil if (tracer == 0) { 49801.1Skamil /* No IPC to communicate with the child */ 49811.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 49821.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 49831.1Skamil 49841.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 49851.1Skamil FORKEE_REQUIRE_SUCCESS( 49861.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 49871.1Skamil 49881.1Skamil forkee_status_stopped(status, SIGSTOP); 49891.1Skamil 49901.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 49911.77Skamil "tracee"); 49921.77Skamil FORKEE_ASSERT( 49931.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 49941.77Skamil 49951.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 49961.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 49971.77Skamil "si_errno=%#x\n", 49981.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 49991.77Skamil info.psi_siginfo.si_errno); 50001.77Skamil 50011.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 50021.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 50031.77Skamil 50041.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 50051.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 50061.1Skamil != -1); 50071.1Skamil 50081.13Schristos DPRINTF("Assert that there exists a thread\n"); 50091.77Skamil FORKEE_ASSERTX(lwp.pl_lwpid > 0); 50101.1Skamil 50111.13Schristos DPRINTF("Assert that lwp thread %d received event " 50121.77Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 50131.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 50141.1Skamil 50151.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50161.77Skamil "tracee\n"); 50171.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 50181.1Skamil != -1); 50191.1Skamil 50201.77Skamil DPRINTF("Assert that there are no more lwp threads in " 50211.77Skamil "tracee\n"); 50221.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 50231.1Skamil 50241.1Skamil /* Resume tracee with PT_CONTINUE */ 50251.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 50261.1Skamil 50271.1Skamil /* Inform parent that tracer has attached to tracee */ 50281.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 50291.77Skamil 50301.1Skamil /* Wait for parent */ 50311.1Skamil CHILD_FROM_PARENT("tracer wait", parent_tracer, msg); 50321.1Skamil 50331.77Skamil /* Wait for tracee and assert that it raised a signal */ 50341.77Skamil FORKEE_REQUIRE_SUCCESS( 50351.77Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 50361.77Skamil 50371.77Skamil forkee_status_stopped(status, SIGINT); 50381.77Skamil 50391.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 50401.77Skamil "child"); 50411.77Skamil FORKEE_ASSERT( 50421.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 50431.77Skamil 50441.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 50451.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 50461.77Skamil "si_errno=%#x\n", 50471.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 50481.77Skamil info.psi_siginfo.si_errno); 50491.77Skamil 50501.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 50511.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 50521.77Skamil 50531.77Skamil memset(&lwp, 0, sizeof(lwp)); 50541.77Skamil 50551.77Skamil for (n = 0; n <= threads; n++) { 50561.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50571.77Skamil "child\n"); 50581.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, 50591.77Skamil sizeof(lwp)) != -1); 50601.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 50611.77Skamil 50621.77Skamil DPRINTF("Assert that the thread exists\n"); 50631.77Skamil FORKEE_ASSERT(lwp.pl_lwpid > 0); 50641.77Skamil 50651.77Skamil DPRINTF("Assert that lwp thread %d received expected " 50661.77Skamil "event\n", lwp.pl_lwpid); 50671.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 50681.77Skamil info.psi_lwpid == lwp.pl_lwpid ? 50691.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 50701.77Skamil } 50711.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50721.77Skamil "tracee\n"); 50731.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 50741.77Skamil != -1); 50751.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 50761.77Skamil 50771.77Skamil DPRINTF("Assert that there are no more threads\n"); 50781.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 50791.77Skamil 50801.77Skamil DPRINTF("Before resuming the child process where it left off " 50811.77Skamil "and without signal to be sent\n"); 50821.77Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL) 50831.77Skamil != -1); 50841.77Skamil 50851.1Skamil /* Wait for tracee and assert that it exited */ 50861.1Skamil FORKEE_REQUIRE_SUCCESS( 50871.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 50881.1Skamil 50891.77Skamil forkee_status_signaled(status, SIGKILL, 0); 50901.1Skamil 50911.13Schristos DPRINTF("Before exiting of the tracer process\n"); 50921.1Skamil _exit(exitval_tracer); 50931.1Skamil } 50941.1Skamil 50951.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 50961.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 50971.1Skamil 50981.77Skamil DPRINTF("Resume the tracee and spawn threads\n"); 50991.77Skamil PARENT_TO_CHILD("spawn threads", parent_tracee, msg); 51001.77Skamil 51011.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 51021.77Skamil PARENT_FROM_CHILD("tracee exit", parent_tracee, msg); 51031.1Skamil 51041.77Skamil DPRINTF("Resume the tracer and let it detect multiple threads\n"); 51051.1Skamil PARENT_TO_CHILD("tracer wait", parent_tracer, msg); 51061.1Skamil 51071.13Schristos DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n", 51081.1Skamil TWAIT_FNAME); 51091.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 51101.1Skamil tracer); 51111.1Skamil 51121.1Skamil validate_status_exited(status, exitval_tracer); 51131.1Skamil 51141.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 51151.1Skamil TWAIT_FNAME); 51161.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 51171.1Skamil tracee); 51181.1Skamil 51191.77Skamil validate_status_signaled(status, SIGKILL, 0); 51201.1Skamil 51211.1Skamil msg_close(&parent_tracer); 51221.1Skamil msg_close(&parent_tracee); 51231.1Skamil} 51241.77Skamil 51251.77Skamil#define ATTACH_LWPINFO(test, threads) \ 51261.77SkamilATF_TC(test); \ 51271.77SkamilATF_TC_HEAD(test, tc) \ 51281.77Skamil{ \ 51291.77Skamil atf_tc_set_md_var(tc, "descr", \ 51301.77Skamil "Verify LWPINFO with the child with " #threads \ 51311.77Skamil " spawned extra threads (tracer is not the original " \ 51321.77Skamil "parent)"); \ 51331.77Skamil} \ 51341.77Skamil \ 51351.77SkamilATF_TC_BODY(test, tc) \ 51361.77Skamil{ \ 51371.77Skamil \ 51381.77Skamil attach_lwpinfo(threads); \ 51391.77Skamil} 51401.77Skamil 51411.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0) 51421.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1) 51431.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2) 51441.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3) 51451.1Skamil#endif 51461.1Skamil 51471.77Skamil/// ---------------------------------------------------------------------------- 51481.77Skamil 51491.1Skamilstatic void 51501.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught) 51511.1Skamil{ 51521.1Skamil const int exitval = 5; 51531.1Skamil const int sigval = SIGINT; 51541.1Skamil const int sigfaked = SIGTRAP; 51551.1Skamil const int sicodefaked = TRAP_BRKPT; 51561.1Skamil pid_t child, wpid; 51571.1Skamil struct sigaction sa; 51581.1Skamil#if defined(TWAIT_HAVE_STATUS) 51591.1Skamil int status; 51601.1Skamil#endif 51611.1Skamil struct ptrace_siginfo info; 51621.1Skamil memset(&info, 0, sizeof(info)); 51631.1Skamil 51641.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 51651.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 51661.1Skamil if (child == 0) { 51671.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 51681.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 51691.1Skamil 51701.79Skamil sa.sa_sigaction = sah; 51711.1Skamil sa.sa_flags = SA_SIGINFO; 51721.1Skamil sigemptyset(&sa.sa_mask); 51731.1Skamil 51741.79Skamil FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL) 51751.79Skamil != -1); 51761.1Skamil 51771.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 51781.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 51791.1Skamil 51801.79Skamil FORKEE_ASSERT_EQ(*signal_caught, 1); 51811.1Skamil 51821.13Schristos DPRINTF("Before exiting of the child process\n"); 51831.1Skamil _exit(exitval); 51841.1Skamil } 51851.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 51861.1Skamil 51871.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51881.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 51891.1Skamil 51901.1Skamil validate_status_stopped(status, sigval); 51911.1Skamil 51921.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 51931.61Skre SYSCALL_REQUIRE( 51941.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 51951.1Skamil 51961.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 51971.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 51981.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 51991.1Skamil info.psi_siginfo.si_errno); 52001.1Skamil 52011.79Skamil if (faked) { 52021.79Skamil DPRINTF("Before setting new faked signal to signo=%d " 52031.79Skamil "si_code=%d\n", sigfaked, sicodefaked); 52041.79Skamil info.psi_siginfo.si_signo = sigfaked; 52051.79Skamil info.psi_siginfo.si_code = sicodefaked; 52061.79Skamil } 52071.1Skamil 52081.13Schristos DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n"); 52091.61Skre SYSCALL_REQUIRE( 52101.61Skre ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1); 52111.1Skamil 52121.79Skamil if (faked) { 52131.79Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 52141.79Skamil "child\n"); 52151.79Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 52161.79Skamil sizeof(info)) != -1); 52171.1Skamil 52181.79Skamil DPRINTF("Before checking siginfo_t\n"); 52191.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked); 52201.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked); 52211.79Skamil } 52221.1Skamil 52231.13Schristos DPRINTF("Before resuming the child process where it left off and " 52241.1Skamil "without signal to be sent\n"); 52251.79Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 52261.79Skamil faked ? sigfaked : sigval) != -1); 52271.1Skamil 52281.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52291.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52301.1Skamil 52311.1Skamil validate_status_exited(status, exitval); 52321.1Skamil 52331.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52341.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 52351.1Skamil} 52361.1Skamil 52371.79Skamil#define PTRACE_SIGINFO(test, faked) \ 52381.79SkamilATF_TC(test); \ 52391.79SkamilATF_TC_HEAD(test, tc) \ 52401.79Skamil{ \ 52411.79Skamil atf_tc_set_md_var(tc, "descr", \ 52421.79Skamil "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls" \ 52431.79Skamil "with%s setting signal to new value", faked ? "" : "out"); \ 52441.79Skamil} \ 52451.79Skamil \ 52461.79Skamilstatic int test##_caught = 0; \ 52471.79Skamil \ 52481.79Skamilstatic void \ 52491.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx) \ 52501.79Skamil{ \ 52511.79Skamil if (faked) { \ 52521.79Skamil FORKEE_ASSERT_EQ(sig, SIGTRAP); \ 52531.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP); \ 52541.79Skamil FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT); \ 52551.79Skamil } else { \ 52561.79Skamil FORKEE_ASSERT_EQ(sig, SIGINT); \ 52571.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGINT); \ 52581.79Skamil FORKEE_ASSERT_EQ(info->si_code, SI_LWP); \ 52591.79Skamil } \ 52601.79Skamil \ 52611.79Skamil ++ test##_caught; \ 52621.79Skamil} \ 52631.79Skamil \ 52641.79SkamilATF_TC_BODY(test, tc) \ 52651.79Skamil{ \ 52661.79Skamil \ 52671.79Skamil ptrace_siginfo(faked, test##_sighandler, & test##_caught); \ 52681.79Skamil} 52691.79Skamil 52701.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false) 52711.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true) 52721.79Skamil 52731.79Skamil/// ---------------------------------------------------------------------------- 52741.79Skamil 52751.97Skamilstatic void 52761.97Skamiltraceme_exec(bool masked, bool ignored) 52771.1Skamil{ 52781.1Skamil const int sigval = SIGTRAP; 52791.1Skamil pid_t child, wpid; 52801.1Skamil#if defined(TWAIT_HAVE_STATUS) 52811.1Skamil int status; 52821.1Skamil#endif 52831.97Skamil struct sigaction sa; 52841.97Skamil struct ptrace_siginfo info; 52851.97Skamil sigset_t intmask; 52861.97Skamil struct kinfo_proc2 kp; 52871.97Skamil size_t len = sizeof(kp); 52881.97Skamil 52891.97Skamil int name[6]; 52901.97Skamil const size_t namelen = __arraycount(name); 52911.97Skamil ki_sigset_t kp_sigmask; 52921.97Skamil ki_sigset_t kp_sigignore; 52931.1Skamil 52941.1Skamil memset(&info, 0, sizeof(info)); 52951.1Skamil 52961.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 52971.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 52981.1Skamil if (child == 0) { 52991.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 53001.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 53011.1Skamil 53021.97Skamil if (masked) { 53031.97Skamil sigemptyset(&intmask); 53041.97Skamil sigaddset(&intmask, sigval); 53051.97Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 53061.97Skamil } 53071.97Skamil 53081.97Skamil if (ignored) { 53091.97Skamil memset(&sa, 0, sizeof(sa)); 53101.97Skamil sa.sa_handler = SIG_IGN; 53111.97Skamil sigemptyset(&sa.sa_mask); 53121.97Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 53131.97Skamil } 53141.97Skamil 53151.13Schristos DPRINTF("Before calling execve(2) from child\n"); 53161.1Skamil execlp("/bin/echo", "/bin/echo", NULL); 53171.1Skamil 53181.1Skamil FORKEE_ASSERT(0 && "Not reached"); 53191.1Skamil } 53201.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 53211.1Skamil 53221.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53231.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 53241.1Skamil 53251.1Skamil validate_status_stopped(status, sigval); 53261.1Skamil 53271.97Skamil name[0] = CTL_KERN, 53281.97Skamil name[1] = KERN_PROC2, 53291.97Skamil name[2] = KERN_PROC_PID; 53301.97Skamil name[3] = getpid(); 53311.97Skamil name[4] = sizeof(kp); 53321.97Skamil name[5] = 1; 53331.97Skamil 53341.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 53351.97Skamil 53361.97Skamil if (masked) 53371.97Skamil kp_sigmask = kp.p_sigmask; 53381.97Skamil 53391.97Skamil if (ignored) 53401.97Skamil kp_sigignore = kp.p_sigignore; 53411.97Skamil 53421.97Skamil name[3] = getpid(); 53431.97Skamil 53441.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 53451.97Skamil 53461.97Skamil if (masked) { 53471.97Skamil DPRINTF("kp_sigmask=" 53481.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53491.97Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 53501.97Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 53511.97Skamil 53521.97Skamil DPRINTF("kp.p_sigmask=" 53531.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53541.97Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 53551.97Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 53561.97Skamil 53571.97Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 53581.97Skamil sizeof(kp_sigmask))); 53591.97Skamil } 53601.97Skamil 53611.97Skamil if (ignored) { 53621.97Skamil DPRINTF("kp_sigignore=" 53631.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53641.97Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 53651.97Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 53661.97Skamil 53671.97Skamil DPRINTF("kp.p_sigignore=" 53681.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53691.97Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 53701.97Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 53711.97Skamil 53721.97Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 53731.97Skamil sizeof(kp_sigignore))); 53741.97Skamil } 53751.97Skamil 53761.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 53771.61Skre SYSCALL_REQUIRE( 53781.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 53791.1Skamil 53801.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 53811.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 53821.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 53831.1Skamil info.psi_siginfo.si_errno); 53841.1Skamil 53851.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 53861.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 53871.1Skamil 53881.13Schristos DPRINTF("Before resuming the child process where it left off and " 53891.1Skamil "without signal to be sent\n"); 53901.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 53911.1Skamil 53921.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53931.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 53941.1Skamil 53951.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53961.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 53971.1Skamil} 53981.1Skamil 53991.97Skamil#define TRACEME_EXEC(test, masked, ignored) \ 54001.97SkamilATF_TC(test); \ 54011.97SkamilATF_TC_HEAD(test, tc) \ 54021.97Skamil{ \ 54031.97Skamil atf_tc_set_md_var(tc, "descr", \ 54041.97Skamil "Detect SIGTRAP TRAP_EXEC from " \ 54051.97Skamil "child%s%s", masked ? " with masked signal" : "", \ 54061.97Skamil masked ? " with ignored signal" : ""); \ 54071.97Skamil} \ 54081.97Skamil \ 54091.97SkamilATF_TC_BODY(test, tc) \ 54101.97Skamil{ \ 54111.97Skamil \ 54121.97Skamil traceme_exec(masked, ignored); \ 54131.97Skamil} 54141.97Skamil 54151.97SkamilTRACEME_EXEC(traceme_exec, false, false) 54161.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false) 54171.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true) 54181.97Skamil 54191.82Skamil/// ---------------------------------------------------------------------------- 54201.82Skamil 54211.83Skamilstatic volatile int done; 54221.1Skamil 54231.83Skamilstatic void * 54241.83Skamiltrace_threads_cb(void *arg __unused) 54251.1Skamil{ 54261.1Skamil 54271.83Skamil done++; 54281.83Skamil 54291.83Skamil while (done < 3) 54301.83Skamil continue; 54311.83Skamil 54321.83Skamil return NULL; 54331.1Skamil} 54341.1Skamil 54351.83Skamilstatic void 54361.83Skamiltrace_threads(bool trace_create, bool trace_exit) 54371.1Skamil{ 54381.1Skamil const int sigval = SIGSTOP; 54391.1Skamil pid_t child, wpid; 54401.1Skamil#if defined(TWAIT_HAVE_STATUS) 54411.1Skamil int status; 54421.1Skamil#endif 54431.1Skamil ptrace_state_t state; 54441.1Skamil const int slen = sizeof(state); 54451.1Skamil ptrace_event_t event; 54461.1Skamil const int elen = sizeof(event); 54471.83Skamil struct ptrace_siginfo info; 54481.83Skamil 54491.83Skamil pthread_t t[3]; 54501.83Skamil int rv; 54511.83Skamil size_t n; 54521.1Skamil lwpid_t lid; 54531.83Skamil 54541.83Skamil /* Track created and exited threads */ 54551.83Skamil bool traced_lwps[__arraycount(t)]; 54561.83Skamil 54571.120Skamil if (trace_create || trace_exit) 54581.119Skamil atf_tc_skip("PR kern/51995"); 54591.1Skamil 54601.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 54611.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 54621.1Skamil if (child == 0) { 54631.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 54641.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 54651.1Skamil 54661.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 54671.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 54681.1Skamil 54691.83Skamil for (n = 0; n < __arraycount(t); n++) { 54701.83Skamil rv = pthread_create(&t[n], NULL, trace_threads_cb, 54711.83Skamil NULL); 54721.83Skamil FORKEE_ASSERT(rv == 0); 54731.83Skamil } 54741.1Skamil 54751.83Skamil for (n = 0; n < __arraycount(t); n++) { 54761.83Skamil rv = pthread_join(t[n], NULL); 54771.83Skamil FORKEE_ASSERT(rv == 0); 54781.83Skamil } 54791.1Skamil 54801.83Skamil /* 54811.83Skamil * There is race between _exit() and pthread_join() detaching 54821.83Skamil * a thread. For simplicity kill the process after detecting 54831.83Skamil * LWP events. 54841.83Skamil */ 54851.83Skamil while (true) 54861.83Skamil continue; 54871.1Skamil 54881.83Skamil FORKEE_ASSERT(0 && "Not reached"); 54891.1Skamil } 54901.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 54911.1Skamil 54921.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54931.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 54941.1Skamil 54951.1Skamil validate_status_stopped(status, sigval); 54961.1Skamil 54971.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 54981.83Skamil SYSCALL_REQUIRE( 54991.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55001.1Skamil 55011.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55021.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 55031.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55041.83Skamil info.psi_siginfo.si_errno); 55051.1Skamil 55061.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 55071.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 55081.1Skamil 55091.83Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 55101.83Skamil memset(&event, 0, sizeof(event)); 55111.83Skamil if (trace_create) 55121.83Skamil event.pe_set_event |= PTRACE_LWP_CREATE; 55131.83Skamil if (trace_exit) 55141.83Skamil event.pe_set_event |= PTRACE_LWP_EXIT; 55151.83Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 55161.1Skamil 55171.13Schristos DPRINTF("Before resuming the child process where it left off and " 55181.1Skamil "without signal to be sent\n"); 55191.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 55201.1Skamil 55211.83Skamil memset(traced_lwps, 0, sizeof(traced_lwps)); 55221.1Skamil 55231.83Skamil for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) { 55241.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 55251.83Skamil "SIGTRAP\n", TWAIT_FNAME); 55261.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 55271.83Skamil child); 55281.1Skamil 55291.83Skamil validate_status_stopped(status, SIGTRAP); 55301.1Skamil 55311.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 55321.83Skamil "child\n"); 55331.83Skamil SYSCALL_REQUIRE( 55341.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55351.1Skamil 55361.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55371.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 55381.83Skamil "si_errno=%#x\n", 55391.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55401.83Skamil info.psi_siginfo.si_errno); 55411.1Skamil 55421.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 55431.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 55441.1Skamil 55451.83Skamil SYSCALL_REQUIRE( 55461.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 55471.1Skamil 55481.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 55491.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 55501.1Skamil 55511.83Skamil lid = state.pe_lwp; 55521.83Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 55531.1Skamil 55541.83Skamil traced_lwps[lid - 1] = true; 55551.1Skamil 55561.83Skamil DPRINTF("Before resuming the child process where it left off " 55571.83Skamil "and without signal to be sent\n"); 55581.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 55591.83Skamil } 55601.1Skamil 55611.83Skamil for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) { 55621.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 55631.83Skamil "SIGTRAP\n", TWAIT_FNAME); 55641.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 55651.83Skamil child); 55661.1Skamil 55671.83Skamil validate_status_stopped(status, SIGTRAP); 55681.1Skamil 55691.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 55701.83Skamil "child\n"); 55711.83Skamil SYSCALL_REQUIRE( 55721.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55731.1Skamil 55741.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55751.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 55761.83Skamil "si_errno=%#x\n", 55771.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55781.83Skamil info.psi_siginfo.si_errno); 55791.1Skamil 55801.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 55811.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 55821.1Skamil 55831.83Skamil SYSCALL_REQUIRE( 55841.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 55851.1Skamil 55861.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 55871.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 55881.1Skamil 55891.83Skamil lid = state.pe_lwp; 55901.83Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 55911.1Skamil 55921.83Skamil if (trace_create) { 55931.83Skamil ATF_REQUIRE(traced_lwps[lid - 1] == true); 55941.83Skamil traced_lwps[lid - 1] = false; 55951.83Skamil } 55961.1Skamil 55971.83Skamil DPRINTF("Before resuming the child process where it left off " 55981.83Skamil "and without signal to be sent\n"); 55991.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56001.83Skamil } 56011.1Skamil 56021.83Skamil kill(child, SIGKILL); 56031.1Skamil 56041.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 56051.1Skamil TWAIT_FNAME); 56061.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56071.1Skamil 56081.83Skamil validate_status_signaled(status, SIGKILL, 0); 56091.1Skamil 56101.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 56111.1Skamil TWAIT_FNAME); 56121.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 56131.1Skamil} 56141.1Skamil 56151.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit) \ 56161.83SkamilATF_TC(test); \ 56171.83SkamilATF_TC_HEAD(test, tc) \ 56181.83Skamil{ \ 56191.83Skamil atf_tc_set_md_var(tc, "descr", \ 56201.83Skamil "Verify spawning threads with%s tracing LWP create and" \ 56211.83Skamil "with%s tracing LWP exit", trace_create ? "" : "out", \ 56221.83Skamil trace_exit ? "" : "out"); \ 56231.83Skamil} \ 56241.83Skamil \ 56251.83SkamilATF_TC_BODY(test, tc) \ 56261.83Skamil{ \ 56271.83Skamil \ 56281.83Skamil trace_threads(trace_create, trace_exit); \ 56291.83Skamil} 56301.83Skamil 56311.119SkamilTRACE_THREADS(trace_thread_nolwpevents, false, false) 56321.119SkamilTRACE_THREADS(trace_thread_lwpexit, false, true) 56331.119SkamilTRACE_THREADS(trace_thread_lwpcreate, true, false) 56341.119SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true) 56351.83Skamil 56361.83Skamil/// ---------------------------------------------------------------------------- 56371.83Skamil 56381.84SkamilATF_TC(signal_mask_unrelated); 56391.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc) 56401.1Skamil{ 56411.1Skamil atf_tc_set_md_var(tc, "descr", 56421.1Skamil "Verify that masking single unrelated signal does not stop tracer " 56431.1Skamil "from catching other signals"); 56441.1Skamil} 56451.1Skamil 56461.84SkamilATF_TC_BODY(signal_mask_unrelated, tc) 56471.1Skamil{ 56481.1Skamil const int exitval = 5; 56491.1Skamil const int sigval = SIGSTOP; 56501.1Skamil const int sigmasked = SIGTRAP; 56511.1Skamil const int signotmasked = SIGINT; 56521.1Skamil pid_t child, wpid; 56531.1Skamil#if defined(TWAIT_HAVE_STATUS) 56541.1Skamil int status; 56551.1Skamil#endif 56561.1Skamil sigset_t intmask; 56571.1Skamil 56581.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 56591.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 56601.1Skamil if (child == 0) { 56611.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 56621.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 56631.1Skamil 56641.1Skamil sigemptyset(&intmask); 56651.1Skamil sigaddset(&intmask, sigmasked); 56661.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 56671.1Skamil 56681.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 56691.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 56701.1Skamil 56711.13Schristos DPRINTF("Before raising %s from child\n", 56721.1Skamil strsignal(signotmasked)); 56731.1Skamil FORKEE_ASSERT(raise(signotmasked) == 0); 56741.1Skamil 56751.13Schristos DPRINTF("Before exiting of the child process\n"); 56761.1Skamil _exit(exitval); 56771.1Skamil } 56781.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 56791.1Skamil 56801.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56811.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56821.1Skamil 56831.1Skamil validate_status_stopped(status, sigval); 56841.1Skamil 56851.13Schristos DPRINTF("Before resuming the child process where it left off and " 56861.1Skamil "without signal to be sent\n"); 56871.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56881.1Skamil 56891.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56901.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56911.1Skamil 56921.1Skamil validate_status_stopped(status, signotmasked); 56931.1Skamil 56941.13Schristos DPRINTF("Before resuming the child process where it left off and " 56951.1Skamil "without signal to be sent\n"); 56961.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56971.1Skamil 56981.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56991.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57001.1Skamil 57011.1Skamil validate_status_exited(status, exitval); 57021.1Skamil 57031.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57041.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 57051.1Skamil} 57061.1Skamil 57071.84Skamil/// ---------------------------------------------------------------------------- 57081.84Skamil 57091.1Skamil#if defined(TWAIT_HAVE_PID) 57101.99Skamilstatic void 57111.126Skamilfork2_body(const char *fn, bool masked, bool ignored) 57121.1Skamil{ 57131.1Skamil const int exitval = 5; 57141.126Skamil const int exitval2 = 0; /* Match exit status from /bin/echo */ 57151.1Skamil const int sigval = SIGSTOP; 57161.99Skamil pid_t child, child2 = 0, wpid; 57171.1Skamil#if defined(TWAIT_HAVE_STATUS) 57181.1Skamil int status; 57191.1Skamil#endif 57201.1Skamil ptrace_state_t state; 57211.1Skamil const int slen = sizeof(state); 57221.1Skamil ptrace_event_t event; 57231.1Skamil const int elen = sizeof(event); 57241.99Skamil struct sigaction sa; 57251.99Skamil struct ptrace_siginfo info; 57261.99Skamil sigset_t intmask; 57271.99Skamil struct kinfo_proc2 kp; 57281.99Skamil size_t len = sizeof(kp); 57291.99Skamil 57301.99Skamil int name[6]; 57311.99Skamil const size_t namelen = __arraycount(name); 57321.99Skamil ki_sigset_t kp_sigmask; 57331.99Skamil ki_sigset_t kp_sigignore; 57341.1Skamil 57351.126Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 57361.14Schristos 57371.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 57381.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 57391.1Skamil if (child == 0) { 57401.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 57411.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 57421.1Skamil 57431.99Skamil if (masked) { 57441.99Skamil sigemptyset(&intmask); 57451.99Skamil sigaddset(&intmask, SIGTRAP); 57461.99Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 57471.99Skamil } 57481.99Skamil 57491.99Skamil if (ignored) { 57501.99Skamil memset(&sa, 0, sizeof(sa)); 57511.99Skamil sa.sa_handler = SIG_IGN; 57521.99Skamil sigemptyset(&sa.sa_mask); 57531.99Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 57541.99Skamil } 57551.1Skamil 57561.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 57571.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 57581.1Skamil 57591.126Skamil if (strcmp(fn, "spawn") == 0) { 57601.126Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 57611.126Skamil arg[0], NULL, NULL, arg, NULL), 0); 57621.126Skamil } else { 57631.126Skamil if (strcmp(fn, "fork") == 0) { 57641.126Skamil FORKEE_ASSERT((child2 = fork()) != -1); 57651.126Skamil } else { 57661.126Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 57671.126Skamil } 57681.126Skamil if (child2 == 0) 57691.126Skamil _exit(exitval2); 57701.126Skamil } 57711.1Skamil 57721.1Skamil FORKEE_REQUIRE_SUCCESS 57731.99Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 57741.1Skamil 57751.1Skamil forkee_status_exited(status, exitval2); 57761.1Skamil 57771.13Schristos DPRINTF("Before exiting of the child process\n"); 57781.1Skamil _exit(exitval); 57791.1Skamil } 57801.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 57811.1Skamil 57821.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57831.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57841.1Skamil 57851.1Skamil validate_status_stopped(status, sigval); 57861.1Skamil 57871.99Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 57881.99Skamil SYSCALL_REQUIRE( 57891.99Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 57901.99Skamil 57911.99Skamil DPRINTF("Before checking siginfo_t\n"); 57921.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 57931.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 57941.1Skamil 57951.99Skamil name[0] = CTL_KERN, 57961.99Skamil name[1] = KERN_PROC2, 57971.99Skamil name[2] = KERN_PROC_PID; 57981.99Skamil name[3] = child; 57991.99Skamil name[4] = sizeof(kp); 58001.99Skamil name[5] = 1; 58011.1Skamil 58021.99Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 58031.1Skamil 58041.99Skamil if (masked) 58051.99Skamil kp_sigmask = kp.p_sigmask; 58061.1Skamil 58071.99Skamil if (ignored) 58081.99Skamil kp_sigignore = kp.p_sigignore; 58091.1Skamil 58101.126Skamil DPRINTF("Set 0%s%s%s%s in EVENT_MASK for the child %d\n", 58111.126Skamil strcmp(fn, "spawn") == 0 ? "|PTRACE_POSIX_SPAWN" : "", 58121.126Skamil strcmp(fn, "fork") == 0 ? "|PTRACE_FORK" : "", 58131.126Skamil strcmp(fn, "vfork") == 0 ? "|PTRACE_VFORK" : "", 58141.126Skamil strcmp(fn, "vforkdone") == 0 ? "|PTRACE_VFORK_DONE" : "", child); 58151.99Skamil event.pe_set_event = 0; 58161.126Skamil if (strcmp(fn, "spawn") == 0) 58171.126Skamil event.pe_set_event |= PTRACE_POSIX_SPAWN; 58181.126Skamil if (strcmp(fn, "fork") == 0) 58191.99Skamil event.pe_set_event |= PTRACE_FORK; 58201.126Skamil if (strcmp(fn, "vfork") == 0) 58211.99Skamil event.pe_set_event |= PTRACE_VFORK; 58221.126Skamil if (strcmp(fn, "vforkdone") == 0) 58231.99Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 58241.99Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 58251.1Skamil 58261.99Skamil DPRINTF("Before resuming the child process where it left off and " 58271.99Skamil "without signal to be sent\n"); 58281.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 58291.1Skamil 58301.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 58311.126Skamil strcmp(fn, "vfork") == 0) { 58321.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 58331.99Skamil child); 58341.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 58351.99Skamil child); 58361.1Skamil 58371.99Skamil validate_status_stopped(status, SIGTRAP); 58381.1Skamil 58391.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 58401.1Skamil 58411.99Skamil if (masked) { 58421.99Skamil DPRINTF("kp_sigmask=" 58431.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58441.99Skamil PRIx32 "\n", 58451.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 58461.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 58471.1Skamil 58481.99Skamil DPRINTF("kp.p_sigmask=" 58491.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58501.99Skamil PRIx32 "\n", 58511.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 58521.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 58531.1Skamil 58541.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 58551.99Skamil sizeof(kp_sigmask))); 58561.99Skamil } 58571.1Skamil 58581.99Skamil if (ignored) { 58591.99Skamil DPRINTF("kp_sigignore=" 58601.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58611.99Skamil PRIx32 "\n", 58621.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 58631.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 58641.1Skamil 58651.99Skamil DPRINTF("kp.p_sigignore=" 58661.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58671.99Skamil PRIx32 "\n", 58681.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 58691.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 58701.1Skamil 58711.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 58721.99Skamil sizeof(kp_sigignore))); 58731.99Skamil } 58741.1Skamil 58751.99Skamil SYSCALL_REQUIRE( 58761.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 58771.126Skamil if (strcmp(fn, "spawn") == 0) { 58781.126Skamil ATF_REQUIRE_EQ( 58791.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 58801.126Skamil PTRACE_POSIX_SPAWN); 58811.126Skamil } 58821.126Skamil if (strcmp(fn, "fork") == 0) { 58831.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 58841.99Skamil PTRACE_FORK); 58851.99Skamil } 58861.126Skamil if (strcmp(fn, "vfork") == 0) { 58871.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 58881.99Skamil PTRACE_VFORK); 58891.99Skamil } 58901.1Skamil 58911.99Skamil child2 = state.pe_other_pid; 58921.99Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 58931.1Skamil 58941.99Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 58951.99Skamil "%d\n", TWAIT_FNAME, child2, child); 58961.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 58971.99Skamil child2); 58981.1Skamil 58991.99Skamil validate_status_stopped(status, SIGTRAP); 59001.1Skamil 59011.99Skamil name[3] = child2; 59021.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 59031.1Skamil 59041.99Skamil if (masked) { 59051.99Skamil DPRINTF("kp_sigmask=" 59061.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59071.99Skamil PRIx32 "\n", 59081.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 59091.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 59101.1Skamil 59111.99Skamil DPRINTF("kp.p_sigmask=" 59121.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59131.99Skamil PRIx32 "\n", 59141.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 59151.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 59161.14Schristos 59171.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 59181.99Skamil sizeof(kp_sigmask))); 59191.99Skamil } 59201.1Skamil 59211.99Skamil if (ignored) { 59221.99Skamil DPRINTF("kp_sigignore=" 59231.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59241.99Skamil PRIx32 "\n", 59251.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 59261.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 59271.1Skamil 59281.99Skamil DPRINTF("kp.p_sigignore=" 59291.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59301.99Skamil PRIx32 "\n", 59311.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 59321.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 59331.1Skamil 59341.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 59351.99Skamil sizeof(kp_sigignore))); 59361.99Skamil } 59371.1Skamil 59381.99Skamil SYSCALL_REQUIRE( 59391.99Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 59401.126Skamil if (strcmp(fn, "spawn") == 0) { 59411.126Skamil ATF_REQUIRE_EQ( 59421.126Skamil state.pe_report_event & PTRACE_POSIX_SPAWN, 59431.126Skamil PTRACE_POSIX_SPAWN); 59441.126Skamil } 59451.126Skamil if (strcmp(fn, "fork") == 0) { 59461.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 59471.99Skamil PTRACE_FORK); 59481.99Skamil } 59491.126Skamil if (strcmp(fn, "vfork") == 0) { 59501.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 59511.99Skamil PTRACE_VFORK); 59521.99Skamil } 59531.1Skamil 59541.99Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 59551.1Skamil 59561.99Skamil DPRINTF("Before resuming the forkee process where it left off " 59571.99Skamil "and without signal to be sent\n"); 59581.99Skamil SYSCALL_REQUIRE( 59591.99Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 59601.1Skamil 59611.99Skamil DPRINTF("Before resuming the child process where it left off " 59621.99Skamil "and without signal to be sent\n"); 59631.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 59641.1Skamil } 59651.1Skamil 59661.126Skamil if (strcmp(fn, "vforkdone") == 0) { 59671.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 59681.99Skamil child); 59691.99Skamil TWAIT_REQUIRE_SUCCESS( 59701.99Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 59711.1Skamil 59721.99Skamil validate_status_stopped(status, SIGTRAP); 59731.1Skamil 59741.99Skamil name[3] = child; 59751.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 59761.1Skamil 59771.102Skamil /* 59781.102Skamil * SIGCHLD is now pending in the signal queue and 59791.102Skamil * the kernel presents it to userland as a masked signal. 59801.102Skamil */ 59811.102Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 59821.102Skamil 59831.99Skamil if (masked) { 59841.99Skamil DPRINTF("kp_sigmask=" 59851.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59861.99Skamil PRIx32 "\n", 59871.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 59881.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 59891.1Skamil 59901.99Skamil DPRINTF("kp.p_sigmask=" 59911.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59921.99Skamil PRIx32 "\n", 59931.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 59941.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 59951.1Skamil 59961.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 59971.99Skamil sizeof(kp_sigmask))); 59981.99Skamil } 59991.1Skamil 60001.99Skamil if (ignored) { 60011.99Skamil DPRINTF("kp_sigignore=" 60021.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60031.99Skamil PRIx32 "\n", 60041.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 60051.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 60061.1Skamil 60071.99Skamil DPRINTF("kp.p_sigignore=" 60081.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 60091.99Skamil PRIx32 "\n", 60101.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 60111.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 60121.1Skamil 60131.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 60141.99Skamil sizeof(kp_sigignore))); 60151.99Skamil } 60161.1Skamil 60171.99Skamil SYSCALL_REQUIRE( 60181.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 60191.99Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 60201.1Skamil 60211.99Skamil child2 = state.pe_other_pid; 60221.99Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 60231.99Skamil child2); 60241.1Skamil 60251.99Skamil DPRINTF("Before resuming the child process where it left off " 60261.99Skamil "and without signal to be sent\n"); 60271.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60281.99Skamil } 60291.1Skamil 60301.126Skamil if (strcmp(fn, "spawn") == 0 || strcmp(fn, "fork") == 0 || 60311.126Skamil strcmp(fn, "vfork") == 0) { 60321.99Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 60331.99Skamil "\n", TWAIT_FNAME); 60341.99Skamil TWAIT_REQUIRE_SUCCESS( 60351.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 60361.1Skamil 60371.99Skamil validate_status_exited(status, exitval2); 60381.1Skamil 60391.99Skamil DPRINTF("Before calling %s() for the forkee - expected no " 60401.99Skamil "process\n", TWAIT_FNAME); 60411.99Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 60421.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 60431.99Skamil } 60441.1Skamil 60451.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 60461.1Skamil "SIGCHLD\n", TWAIT_FNAME); 60471.57Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60481.1Skamil 60491.1Skamil validate_status_stopped(status, SIGCHLD); 60501.1Skamil 60511.57Skamil DPRINTF("Before resuming the child process where it left off and " 60521.1Skamil "without signal to be sent\n"); 60531.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60541.1Skamil 60551.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 60561.1Skamil TWAIT_FNAME); 60571.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60581.1Skamil 60591.1Skamil validate_status_exited(status, exitval); 60601.1Skamil 60611.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 60621.57Skamil TWAIT_FNAME); 60631.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 60641.1Skamil} 60651.1Skamil 60661.126Skamil#define FORK2_TEST(name,fn,masked,ignored) \ 60671.99SkamilATF_TC(name); \ 60681.99SkamilATF_TC_HEAD(name, tc) \ 60691.99Skamil{ \ 60701.126Skamil atf_tc_set_md_var(tc, "descr", "Verify that " fn " is caught " \ 60711.99Skamil "regardless of signal %s%s", \ 60721.99Skamil masked ? "masked" : "", ignored ? "ignored" : ""); \ 60731.99Skamil} \ 60741.99Skamil \ 60751.99SkamilATF_TC_BODY(name, tc) \ 60761.99Skamil{ \ 60771.99Skamil \ 60781.126Skamil fork2_body(fn, masked, ignored); \ 60791.1Skamil} 60801.1Skamil 60811.126SkamilFORK2_TEST(posix_spawn_singalmasked, "spawn", true, false) 60821.126SkamilFORK2_TEST(posix_spawn_singalignored, "spawn", false, true) 60831.126SkamilFORK2_TEST(fork_singalmasked, "fork", true, false) 60841.126SkamilFORK2_TEST(fork_singalignored, "fork", false, true) 60851.110Skamil#if TEST_VFORK_ENABLED 60861.126SkamilFORK2_TEST(vfork_singalmasked, "vfork", true, false) 60871.126SkamilFORK2_TEST(vfork_singalignored, "vfork", false, true) 60881.126SkamilFORK2_TEST(vforkdone_singalmasked, "vforkdone", true, false) 60891.126SkamilFORK2_TEST(vforkdone_singalignored, "vforkdone", false, true) 60901.1Skamil#endif 60911.110Skamil#endif 60921.1Skamil 60931.99Skamil/// ---------------------------------------------------------------------------- 60941.1Skamil 60951.83Skamilvolatile lwpid_t the_lwp_id = 0; 60961.83Skamil 60971.83Skamilstatic void 60981.83Skamillwp_main_func(void *arg) 60991.83Skamil{ 61001.83Skamil the_lwp_id = _lwp_self(); 61011.83Skamil _lwp_exit(); 61021.83Skamil} 61031.83Skamil 61041.1SkamilATF_TC(signal9); 61051.1SkamilATF_TC_HEAD(signal9, tc) 61061.1Skamil{ 61071.1Skamil atf_tc_set_md_var(tc, "descr", 61081.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 61091.1Skamil "catching PTRACE_LWP_CREATE breakpoint"); 61101.1Skamil} 61111.1Skamil 61121.1SkamilATF_TC_BODY(signal9, tc) 61131.1Skamil{ 61141.1Skamil const int exitval = 5; 61151.1Skamil const int sigval = SIGSTOP; 61161.1Skamil const int sigmasked = SIGTRAP; 61171.1Skamil pid_t child, wpid; 61181.1Skamil#if defined(TWAIT_HAVE_STATUS) 61191.1Skamil int status; 61201.1Skamil#endif 61211.1Skamil sigset_t intmask; 61221.1Skamil ptrace_state_t state; 61231.1Skamil const int slen = sizeof(state); 61241.1Skamil ptrace_event_t event; 61251.1Skamil const int elen = sizeof(event); 61261.1Skamil ucontext_t uc; 61271.1Skamil lwpid_t lid; 61281.1Skamil static const size_t ssize = 16*1024; 61291.1Skamil void *stack; 61301.1Skamil 61311.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 61321.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 61331.1Skamil if (child == 0) { 61341.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 61351.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 61361.1Skamil 61371.1Skamil sigemptyset(&intmask); 61381.1Skamil sigaddset(&intmask, sigmasked); 61391.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 61401.1Skamil 61411.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 61421.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 61431.1Skamil 61441.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 61451.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 61461.1Skamil 61471.13Schristos DPRINTF("Before making context for new lwp in child\n"); 61481.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 61491.1Skamil 61501.13Schristos DPRINTF("Before creating new in child\n"); 61511.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 61521.1Skamil 61531.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 61541.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 61551.1Skamil 61561.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 61571.1Skamil "are the same\n", lid, the_lwp_id); 61581.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 61591.1Skamil 61601.13Schristos DPRINTF("Before exiting of the child process\n"); 61611.1Skamil _exit(exitval); 61621.1Skamil } 61631.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 61641.1Skamil 61651.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 61661.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61671.1Skamil 61681.1Skamil validate_status_stopped(status, sigval); 61691.1Skamil 61701.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 61711.1Skamil event.pe_set_event = PTRACE_LWP_CREATE; 61721.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 61731.1Skamil 61741.13Schristos DPRINTF("Before resuming the child process where it left off and " 61751.1Skamil "without signal to be sent\n"); 61761.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 61771.1Skamil 61781.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 61791.1Skamil "SIGTRAP\n", TWAIT_FNAME); 61801.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61811.1Skamil 61821.1Skamil validate_status_stopped(status, sigmasked); 61831.1Skamil 61841.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 61851.1Skamil 61861.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE); 61871.1Skamil 61881.1Skamil lid = state.pe_lwp; 61891.13Schristos DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 61901.1Skamil 61911.13Schristos DPRINTF("Before resuming the child process where it left off and " 61921.1Skamil "without signal to be sent\n"); 61931.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 61941.1Skamil 61951.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 61961.1Skamil TWAIT_FNAME); 61971.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61981.1Skamil 61991.1Skamil validate_status_exited(status, exitval); 62001.1Skamil 62011.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 62021.1Skamil TWAIT_FNAME); 62031.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 62041.1Skamil} 62051.1Skamil 62061.1SkamilATF_TC(signal10); 62071.1SkamilATF_TC_HEAD(signal10, tc) 62081.1Skamil{ 62091.1Skamil atf_tc_set_md_var(tc, "descr", 62101.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 62111.1Skamil "catching PTRACE_LWP_EXIT breakpoint"); 62121.1Skamil} 62131.1Skamil 62141.1SkamilATF_TC_BODY(signal10, tc) 62151.1Skamil{ 62161.1Skamil const int exitval = 5; 62171.1Skamil const int sigval = SIGSTOP; 62181.1Skamil const int sigmasked = SIGTRAP; 62191.1Skamil pid_t child, wpid; 62201.1Skamil#if defined(TWAIT_HAVE_STATUS) 62211.1Skamil int status; 62221.1Skamil#endif 62231.1Skamil sigset_t intmask; 62241.1Skamil ptrace_state_t state; 62251.1Skamil const int slen = sizeof(state); 62261.1Skamil ptrace_event_t event; 62271.1Skamil const int elen = sizeof(event); 62281.1Skamil ucontext_t uc; 62291.1Skamil lwpid_t lid; 62301.1Skamil static const size_t ssize = 16*1024; 62311.1Skamil void *stack; 62321.1Skamil 62331.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 62341.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 62351.1Skamil if (child == 0) { 62361.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 62371.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 62381.1Skamil 62391.1Skamil sigemptyset(&intmask); 62401.1Skamil sigaddset(&intmask, sigmasked); 62411.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 62421.1Skamil 62431.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 62441.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 62451.1Skamil 62461.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 62471.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 62481.1Skamil 62491.13Schristos DPRINTF("Before making context for new lwp in child\n"); 62501.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 62511.1Skamil 62521.13Schristos DPRINTF("Before creating new in child\n"); 62531.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 62541.1Skamil 62551.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 62561.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 62571.1Skamil 62581.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 62591.1Skamil "are the same\n", lid, the_lwp_id); 62601.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 62611.1Skamil 62621.13Schristos DPRINTF("Before exiting of the child process\n"); 62631.1Skamil _exit(exitval); 62641.1Skamil } 62651.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 62661.1Skamil 62671.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 62681.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62691.1Skamil 62701.1Skamil validate_status_stopped(status, sigval); 62711.1Skamil 62721.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 62731.1Skamil event.pe_set_event = PTRACE_LWP_EXIT; 62741.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 62751.1Skamil 62761.13Schristos DPRINTF("Before resuming the child process where it left off and " 62771.1Skamil "without signal to be sent\n"); 62781.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 62791.1Skamil 62801.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 62811.1Skamil "SIGTRAP\n", TWAIT_FNAME); 62821.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62831.1Skamil 62841.1Skamil validate_status_stopped(status, sigmasked); 62851.1Skamil 62861.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 62871.1Skamil 62881.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT); 62891.1Skamil 62901.1Skamil lid = state.pe_lwp; 62911.13Schristos DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 62921.1Skamil 62931.13Schristos DPRINTF("Before resuming the child process where it left off and " 62941.1Skamil "without signal to be sent\n"); 62951.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 62961.1Skamil 62971.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 62981.1Skamil TWAIT_FNAME); 62991.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63001.1Skamil 63011.1Skamil validate_status_exited(status, exitval); 63021.1Skamil 63031.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 63041.1Skamil TWAIT_FNAME); 63051.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 63061.1Skamil} 63071.1Skamil 63081.1Skamilstatic void 63091.1Skamillwp_main_stop(void *arg) 63101.1Skamil{ 63111.1Skamil the_lwp_id = _lwp_self(); 63121.1Skamil 63131.1Skamil raise(SIGTRAP); 63141.1Skamil 63151.1Skamil _lwp_exit(); 63161.1Skamil} 63171.1Skamil 63181.1SkamilATF_TC(suspend1); 63191.1SkamilATF_TC_HEAD(suspend1, tc) 63201.1Skamil{ 63211.1Skamil atf_tc_set_md_var(tc, "descr", 63221.1Skamil "Verify that a thread can be suspended by a debugger and later " 63231.1Skamil "resumed by a tracee"); 63241.1Skamil} 63251.1Skamil 63261.1SkamilATF_TC_BODY(suspend1, tc) 63271.1Skamil{ 63281.1Skamil const int exitval = 5; 63291.1Skamil const int sigval = SIGSTOP; 63301.1Skamil pid_t child, wpid; 63311.1Skamil#if defined(TWAIT_HAVE_STATUS) 63321.1Skamil int status; 63331.1Skamil#endif 63341.1Skamil ucontext_t uc; 63351.1Skamil lwpid_t lid; 63361.1Skamil static const size_t ssize = 16*1024; 63371.1Skamil void *stack; 63381.1Skamil struct ptrace_lwpinfo pl; 63391.1Skamil struct ptrace_siginfo psi; 63401.1Skamil volatile int go = 0; 63411.1Skamil 63421.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 63431.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 63441.1Skamil if (child == 0) { 63451.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 63461.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 63471.1Skamil 63481.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 63491.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 63501.1Skamil 63511.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 63521.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 63531.1Skamil 63541.13Schristos DPRINTF("Before making context for new lwp in child\n"); 63551.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 63561.1Skamil 63571.13Schristos DPRINTF("Before creating new in child\n"); 63581.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 63591.1Skamil 63601.1Skamil while (go == 0) 63611.1Skamil continue; 63621.1Skamil 63631.1Skamil raise(SIGINT); 63641.1Skamil 63651.1Skamil FORKEE_ASSERT(_lwp_continue(lid) == 0); 63661.1Skamil 63671.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 63681.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 63691.1Skamil 63701.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 63711.1Skamil "are the same\n", lid, the_lwp_id); 63721.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 63731.1Skamil 63741.13Schristos DPRINTF("Before exiting of the child process\n"); 63751.1Skamil _exit(exitval); 63761.1Skamil } 63771.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 63781.1Skamil 63791.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 63801.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63811.1Skamil 63821.1Skamil validate_status_stopped(status, sigval); 63831.1Skamil 63841.13Schristos DPRINTF("Before resuming the child process where it left off and " 63851.1Skamil "without signal to be sent\n"); 63861.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63871.1Skamil 63881.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 63891.1Skamil "SIGTRAP\n", TWAIT_FNAME); 63901.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63911.1Skamil 63921.1Skamil validate_status_stopped(status, SIGTRAP); 63931.1Skamil 63941.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 63951.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 63961.1Skamil 63971.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 63981.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 63991.1Skamil 64001.13Schristos DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n", 64011.1Skamil child, getpid()); 64021.13Schristos SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1); 64031.1Skamil 64041.13Schristos DPRINTF("Before resuming the child process where it left off and " 64051.1Skamil "without signal to be sent\n"); 64061.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64071.1Skamil 64081.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 64091.1Skamil "SIGINT\n", TWAIT_FNAME); 64101.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64111.1Skamil 64121.1Skamil validate_status_stopped(status, SIGINT); 64131.1Skamil 64141.1Skamil pl.pl_lwpid = 0; 64151.1Skamil 64161.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 64171.1Skamil while (pl.pl_lwpid != 0) { 64181.1Skamil 64191.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 64201.1Skamil switch (pl.pl_lwpid) { 64211.1Skamil case 1: 64221.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 64231.1Skamil break; 64241.1Skamil case 2: 64251.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 64261.1Skamil break; 64271.1Skamil } 64281.1Skamil } 64291.1Skamil 64301.13Schristos DPRINTF("Before resuming the child process where it left off and " 64311.1Skamil "without signal to be sent\n"); 64321.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64331.1Skamil 64341.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 64351.1Skamil TWAIT_FNAME); 64361.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64371.1Skamil 64381.1Skamil validate_status_exited(status, exitval); 64391.1Skamil 64401.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 64411.1Skamil TWAIT_FNAME); 64421.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 64431.1Skamil} 64441.1Skamil 64451.1SkamilATF_TC(suspend2); 64461.1SkamilATF_TC_HEAD(suspend2, tc) 64471.1Skamil{ 64481.1Skamil atf_tc_set_md_var(tc, "descr", 64491.1Skamil "Verify that the while the only thread within a process is " 64501.1Skamil "suspended, the whole process cannot be unstopped"); 64511.1Skamil} 64521.1Skamil 64531.1SkamilATF_TC_BODY(suspend2, tc) 64541.1Skamil{ 64551.1Skamil const int exitval = 5; 64561.1Skamil const int sigval = SIGSTOP; 64571.1Skamil pid_t child, wpid; 64581.1Skamil#if defined(TWAIT_HAVE_STATUS) 64591.1Skamil int status; 64601.1Skamil#endif 64611.1Skamil struct ptrace_siginfo psi; 64621.1Skamil 64631.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 64641.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 64651.1Skamil if (child == 0) { 64661.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 64671.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 64681.1Skamil 64691.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 64701.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 64711.1Skamil 64721.13Schristos DPRINTF("Before exiting of the child process\n"); 64731.1Skamil _exit(exitval); 64741.1Skamil } 64751.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 64761.1Skamil 64771.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 64781.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64791.1Skamil 64801.1Skamil validate_status_stopped(status, sigval); 64811.1Skamil 64821.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 64831.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 64841.1Skamil 64851.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 64861.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 64871.1Skamil 64881.13Schristos DPRINTF("Before resuming the child process where it left off and " 64891.1Skamil "without signal to be sent\n"); 64901.1Skamil ATF_REQUIRE_ERRNO(EDEADLK, 64911.1Skamil ptrace(PT_CONTINUE, child, (void *)1, 0) == -1); 64921.1Skamil 64931.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 64941.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 64951.1Skamil 64961.13Schristos DPRINTF("Before resuming the child process where it left off and " 64971.1Skamil "without signal to be sent\n"); 64981.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64991.1Skamil 65001.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 65011.1Skamil TWAIT_FNAME); 65021.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65031.1Skamil 65041.1Skamil validate_status_exited(status, exitval); 65051.1Skamil 65061.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 65071.1Skamil TWAIT_FNAME); 65081.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 65091.1Skamil} 65101.1Skamil 65111.1SkamilATF_TC(resume1); 65121.1SkamilATF_TC_HEAD(resume1, tc) 65131.1Skamil{ 65141.1Skamil atf_tc_set_md_var(tc, "descr", 65151.1Skamil "Verify that a thread can be suspended by a debugger and later " 65161.1Skamil "resumed by the debugger"); 65171.1Skamil} 65181.1Skamil 65191.1SkamilATF_TC_BODY(resume1, tc) 65201.1Skamil{ 65211.1Skamil struct msg_fds fds; 65221.1Skamil const int exitval = 5; 65231.1Skamil const int sigval = SIGSTOP; 65241.1Skamil pid_t child, wpid; 65251.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 65261.1Skamil#if defined(TWAIT_HAVE_STATUS) 65271.1Skamil int status; 65281.1Skamil#endif 65291.1Skamil ucontext_t uc; 65301.1Skamil lwpid_t lid; 65311.1Skamil static const size_t ssize = 16*1024; 65321.1Skamil void *stack; 65331.1Skamil struct ptrace_lwpinfo pl; 65341.1Skamil struct ptrace_siginfo psi; 65351.1Skamil 65361.13Schristos SYSCALL_REQUIRE(msg_open(&fds) == 0); 65371.1Skamil 65381.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 65391.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 65401.1Skamil if (child == 0) { 65411.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 65421.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 65431.1Skamil 65441.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 65451.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 65461.1Skamil 65471.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 65481.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 65491.1Skamil 65501.13Schristos DPRINTF("Before making context for new lwp in child\n"); 65511.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 65521.1Skamil 65531.13Schristos DPRINTF("Before creating new in child\n"); 65541.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 65551.1Skamil 65561.1Skamil CHILD_TO_PARENT("Message", fds, msg); 65571.1Skamil 65581.1Skamil raise(SIGINT); 65591.1Skamil 65601.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 65611.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 65621.1Skamil 65631.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 65641.1Skamil "are the same\n", lid, the_lwp_id); 65651.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 65661.1Skamil 65671.13Schristos DPRINTF("Before exiting of the child process\n"); 65681.1Skamil _exit(exitval); 65691.1Skamil } 65701.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 65711.1Skamil 65721.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65731.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65741.1Skamil 65751.1Skamil validate_status_stopped(status, sigval); 65761.1Skamil 65771.13Schristos DPRINTF("Before resuming the child process where it left off and " 65781.1Skamil "without signal to be sent\n"); 65791.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65801.1Skamil 65811.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 65821.1Skamil "SIGTRAP\n", TWAIT_FNAME); 65831.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65841.1Skamil 65851.1Skamil validate_status_stopped(status, SIGTRAP); 65861.1Skamil 65871.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 65881.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 65891.1Skamil 65901.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 65911.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 65921.1Skamil 65931.1Skamil PARENT_FROM_CHILD("Message", fds, msg); 65941.1Skamil 65951.13Schristos DPRINTF("Before resuming the child process where it left off and " 65961.1Skamil "without signal to be sent\n"); 65971.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65981.1Skamil 65991.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 66001.1Skamil "SIGINT\n", TWAIT_FNAME); 66011.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66021.1Skamil 66031.1Skamil validate_status_stopped(status, SIGINT); 66041.1Skamil 66051.1Skamil pl.pl_lwpid = 0; 66061.1Skamil 66071.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 66081.1Skamil while (pl.pl_lwpid != 0) { 66091.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 66101.1Skamil switch (pl.pl_lwpid) { 66111.1Skamil case 1: 66121.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 66131.1Skamil break; 66141.1Skamil case 2: 66151.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 66161.1Skamil break; 66171.1Skamil } 66181.1Skamil } 66191.1Skamil 66201.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 66211.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 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 exited\n", 66281.1Skamil TWAIT_FNAME); 66291.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66301.1Skamil 66311.1Skamil validate_status_exited(status, exitval); 66321.1Skamil 66331.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 66341.1Skamil TWAIT_FNAME); 66351.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 66361.1Skamil 66371.1Skamil msg_close(&fds); 66381.1Skamil} 66391.1Skamil 66401.1SkamilATF_TC(syscall1); 66411.1SkamilATF_TC_HEAD(syscall1, tc) 66421.1Skamil{ 66431.1Skamil atf_tc_set_md_var(tc, "descr", 66441.1Skamil "Verify that getpid(2) can be traced with PT_SYSCALL"); 66451.1Skamil} 66461.1Skamil 66471.1SkamilATF_TC_BODY(syscall1, tc) 66481.1Skamil{ 66491.1Skamil const int exitval = 5; 66501.1Skamil const int sigval = SIGSTOP; 66511.1Skamil pid_t child, wpid; 66521.1Skamil#if defined(TWAIT_HAVE_STATUS) 66531.1Skamil int status; 66541.1Skamil#endif 66551.1Skamil struct ptrace_siginfo info; 66561.1Skamil memset(&info, 0, sizeof(info)); 66571.1Skamil 66581.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 66591.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 66601.1Skamil if (child == 0) { 66611.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 66621.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 66631.1Skamil 66641.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 66651.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 66661.1Skamil 66671.1Skamil syscall(SYS_getpid); 66681.1Skamil 66691.13Schristos DPRINTF("Before exiting of the child process\n"); 66701.1Skamil _exit(exitval); 66711.1Skamil } 66721.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 66731.1Skamil 66741.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66751.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66761.1Skamil 66771.1Skamil validate_status_stopped(status, sigval); 66781.1Skamil 66791.13Schristos DPRINTF("Before resuming the child process where it left off and " 66801.1Skamil "without signal to be sent\n"); 66811.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 66821.1Skamil 66831.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66841.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66851.1Skamil 66861.1Skamil validate_status_stopped(status, SIGTRAP); 66871.1Skamil 66881.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 66891.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 66901.1Skamil 66911.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 66921.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 66931.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 66941.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE); 66951.1Skamil 66961.13Schristos DPRINTF("Before resuming the child process where it left off and " 66971.1Skamil "without signal to be sent\n"); 66981.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 66991.1Skamil 67001.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67011.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67021.1Skamil 67031.1Skamil validate_status_stopped(status, SIGTRAP); 67041.1Skamil 67051.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 67061.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 67071.1Skamil 67081.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 67091.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 67101.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 67111.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX); 67121.1Skamil 67131.13Schristos DPRINTF("Before resuming the child process where it left off and " 67141.1Skamil "without signal to be sent\n"); 67151.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 67161.1Skamil 67171.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67181.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67191.1Skamil 67201.1Skamil validate_status_exited(status, exitval); 67211.1Skamil 67221.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67231.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 67241.1Skamil} 67251.1Skamil 67261.1SkamilATF_TC(syscallemu1); 67271.1SkamilATF_TC_HEAD(syscallemu1, tc) 67281.1Skamil{ 67291.1Skamil atf_tc_set_md_var(tc, "descr", 67301.1Skamil "Verify that exit(2) can be intercepted with PT_SYSCALLEMU"); 67311.1Skamil} 67321.1Skamil 67331.1SkamilATF_TC_BODY(syscallemu1, tc) 67341.1Skamil{ 67351.1Skamil const int exitval = 5; 67361.1Skamil const int sigval = SIGSTOP; 67371.1Skamil pid_t child, wpid; 67381.1Skamil#if defined(TWAIT_HAVE_STATUS) 67391.1Skamil int status; 67401.1Skamil#endif 67411.1Skamil 67421.6Skamil#if defined(__sparc__) && !defined(__sparc64__) 67431.6Skamil /* syscallemu does not work on sparc (32-bit) */ 67441.6Skamil atf_tc_expect_fail("PR kern/52166"); 67451.6Skamil#endif 67461.6Skamil 67471.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 67481.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 67491.1Skamil if (child == 0) { 67501.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 67511.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 67521.1Skamil 67531.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 67541.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 67551.1Skamil 67561.1Skamil syscall(SYS_exit, 100); 67571.1Skamil 67581.13Schristos DPRINTF("Before exiting of the child process\n"); 67591.1Skamil _exit(exitval); 67601.1Skamil } 67611.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 67621.1Skamil 67631.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67641.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67651.1Skamil 67661.1Skamil validate_status_stopped(status, sigval); 67671.1Skamil 67681.13Schristos DPRINTF("Before resuming the child process where it left off and " 67691.1Skamil "without signal to be sent\n"); 67701.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 67711.1Skamil 67721.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67731.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67741.1Skamil 67751.1Skamil validate_status_stopped(status, SIGTRAP); 67761.1Skamil 67771.13Schristos DPRINTF("Set SYSCALLEMU for intercepted syscall\n"); 67781.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1); 67791.1Skamil 67801.13Schristos DPRINTF("Before resuming the child process where it left off and " 67811.1Skamil "without signal to be sent\n"); 67821.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 67831.1Skamil 67841.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67851.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67861.1Skamil 67871.1Skamil validate_status_stopped(status, SIGTRAP); 67881.1Skamil 67891.13Schristos DPRINTF("Before resuming the child process where it left off and " 67901.1Skamil "without signal to be sent\n"); 67911.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 67921.1Skamil 67931.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67941.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67951.1Skamil 67961.1Skamil validate_status_exited(status, exitval); 67971.1Skamil 67981.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67991.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 68001.1Skamil} 68011.1Skamil 68021.103Skamil/// ---------------------------------------------------------------------------- 68031.103Skamil 68041.106Skamilstatic void 68051.106Skamilclone_body(int flags, bool trackfork, bool trackvfork, 68061.106Skamil bool trackvforkdone) 68071.106Skamil{ 68081.106Skamil const int exitval = 5; 68091.106Skamil const int exitval2 = 15; 68101.106Skamil const int sigval = SIGSTOP; 68111.106Skamil pid_t child, child2 = 0, wpid; 68121.106Skamil#if defined(TWAIT_HAVE_STATUS) 68131.106Skamil int status; 68141.106Skamil#endif 68151.106Skamil ptrace_state_t state; 68161.106Skamil const int slen = sizeof(state); 68171.106Skamil ptrace_event_t event; 68181.106Skamil const int elen = sizeof(event); 68191.106Skamil 68201.106Skamil const size_t stack_size = 1024 * 1024; 68211.106Skamil void *stack, *stack_base; 68221.106Skamil 68231.106Skamil stack = malloc(stack_size); 68241.106Skamil ATF_REQUIRE(stack != NULL); 68251.106Skamil 68261.106Skamil#ifdef __MACHINE_STACK_GROWS_UP 68271.106Skamil stack_base = stack; 68281.106Skamil#else 68291.106Skamil stack_base = (char *)stack + stack_size; 68301.106Skamil#endif 68311.106Skamil 68321.106Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 68331.106Skamil SYSCALL_REQUIRE((child = fork()) != -1); 68341.106Skamil if (child == 0) { 68351.106Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 68361.106Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 68371.106Skamil 68381.106Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 68391.106Skamil FORKEE_ASSERT(raise(sigval) == 0); 68401.106Skamil 68411.106Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 68421.106Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 68431.106Skamil 68441.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 68451.106Skamil child2); 68461.106Skamil 68471.106Skamil // XXX WALLSIG? 68481.106Skamil FORKEE_REQUIRE_SUCCESS 68491.106Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 68501.106Skamil 68511.106Skamil forkee_status_exited(status, exitval2); 68521.106Skamil 68531.106Skamil DPRINTF("Before exiting of the child process\n"); 68541.106Skamil _exit(exitval); 68551.106Skamil } 68561.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 68571.106Skamil 68581.106Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 68591.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68601.106Skamil 68611.106Skamil validate_status_stopped(status, sigval); 68621.106Skamil 68631.106Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 68641.106Skamil trackfork ? "|PTRACE_FORK" : "", 68651.106Skamil trackvfork ? "|PTRACE_VFORK" : "", 68661.106Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 68671.106Skamil event.pe_set_event = 0; 68681.106Skamil if (trackfork) 68691.106Skamil event.pe_set_event |= PTRACE_FORK; 68701.106Skamil if (trackvfork) 68711.106Skamil event.pe_set_event |= PTRACE_VFORK; 68721.106Skamil if (trackvforkdone) 68731.106Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 68741.106Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 68751.106Skamil 68761.106Skamil DPRINTF("Before resuming the child process where it left off and " 68771.106Skamil "without signal to be sent\n"); 68781.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68791.106Skamil 68801.106Skamil#if defined(TWAIT_HAVE_PID) 68811.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 68821.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 68831.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 68841.106Skamil child); 68851.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 68861.106Skamil child); 68871.106Skamil 68881.106Skamil validate_status_stopped(status, SIGTRAP); 68891.106Skamil 68901.106Skamil SYSCALL_REQUIRE( 68911.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 68921.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 68931.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 68941.106Skamil PTRACE_FORK); 68951.106Skamil } 68961.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 68971.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 68981.106Skamil PTRACE_VFORK); 68991.106Skamil } 69001.106Skamil 69011.106Skamil child2 = state.pe_other_pid; 69021.106Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 69031.106Skamil 69041.106Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 69051.106Skamil "%d\n", TWAIT_FNAME, child2, child); 69061.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 69071.106Skamil child2); 69081.106Skamil 69091.106Skamil validate_status_stopped(status, SIGTRAP); 69101.106Skamil 69111.106Skamil SYSCALL_REQUIRE( 69121.106Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 69131.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 69141.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 69151.106Skamil PTRACE_FORK); 69161.106Skamil } 69171.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 69181.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 69191.106Skamil PTRACE_VFORK); 69201.106Skamil } 69211.106Skamil 69221.106Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 69231.106Skamil 69241.106Skamil DPRINTF("Before resuming the forkee process where it left off " 69251.106Skamil "and without signal to be sent\n"); 69261.106Skamil SYSCALL_REQUIRE( 69271.106Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 69281.106Skamil 69291.106Skamil DPRINTF("Before resuming the child process where it left off " 69301.106Skamil "and without signal to be sent\n"); 69311.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69321.106Skamil } 69331.106Skamil#endif 69341.106Skamil 69351.106Skamil if (trackvforkdone && (flags & CLONE_VFORK)) { 69361.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 69371.106Skamil child); 69381.106Skamil TWAIT_REQUIRE_SUCCESS( 69391.106Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 69401.106Skamil 69411.106Skamil validate_status_stopped(status, SIGTRAP); 69421.106Skamil 69431.106Skamil SYSCALL_REQUIRE( 69441.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 69451.106Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 69461.106Skamil 69471.106Skamil child2 = state.pe_other_pid; 69481.106Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 69491.106Skamil child2); 69501.106Skamil 69511.106Skamil DPRINTF("Before resuming the child process where it left off " 69521.106Skamil "and without signal to be sent\n"); 69531.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69541.106Skamil } 69551.106Skamil 69561.103Skamil#if defined(TWAIT_HAVE_PID) 69571.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 69581.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 69591.106Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 69601.106Skamil "\n", TWAIT_FNAME); 69611.106Skamil TWAIT_REQUIRE_SUCCESS( 69621.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 69631.106Skamil 69641.106Skamil validate_status_exited(status, exitval2); 69651.106Skamil 69661.106Skamil DPRINTF("Before calling %s() for the forkee - expected no " 69671.106Skamil "process\n", TWAIT_FNAME); 69681.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 69691.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 69701.106Skamil } 69711.106Skamil#endif 69721.106Skamil 69731.106Skamil DPRINTF("Before calling %s() for the child - expected stopped " 69741.106Skamil "SIGCHLD\n", TWAIT_FNAME); 69751.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 69761.106Skamil 69771.106Skamil validate_status_stopped(status, SIGCHLD); 69781.106Skamil 69791.106Skamil DPRINTF("Before resuming the child process where it left off and " 69801.106Skamil "without signal to be sent\n"); 69811.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69821.106Skamil 69831.106Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 69841.106Skamil TWAIT_FNAME); 69851.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 69861.106Skamil 69871.106Skamil validate_status_exited(status, exitval); 69881.103Skamil 69891.106Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 69901.106Skamil TWAIT_FNAME); 69911.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 69921.106Skamil} 69931.103Skamil 69941.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone) \ 69951.106SkamilATF_TC(name); \ 69961.106SkamilATF_TC_HEAD(name, tc) \ 69971.106Skamil{ \ 69981.106Skamil atf_tc_set_md_var(tc, "descr", "Verify clone(%s) " \ 69991.106Skamil "called with 0%s%s%s in EVENT_MASK", \ 70001.106Skamil #flags, \ 70011.106Skamil tfork ? "|PTRACE_FORK" : "", \ 70021.106Skamil tvfork ? "|PTRACE_VFORK" : "", \ 70031.106Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 70041.106Skamil} \ 70051.106Skamil \ 70061.106SkamilATF_TC_BODY(name, tc) \ 70071.106Skamil{ \ 70081.106Skamil \ 70091.106Skamil clone_body(flags, tfork, tvfork, tvforkdone); \ 70101.103Skamil} 70111.103Skamil 70121.106SkamilCLONE_TEST(clone1, 0, false, false, false) 70131.106Skamil#if defined(TWAIT_HAVE_PID) 70141.106SkamilCLONE_TEST(clone2, 0, true, false, false) 70151.106SkamilCLONE_TEST(clone3, 0, false, true, false) 70161.106SkamilCLONE_TEST(clone4, 0, true, true, false) 70171.106Skamil#endif 70181.106SkamilCLONE_TEST(clone5, 0, false, false, true) 70191.106Skamil#if defined(TWAIT_HAVE_PID) 70201.106SkamilCLONE_TEST(clone6, 0, true, false, true) 70211.106SkamilCLONE_TEST(clone7, 0, false, true, true) 70221.106SkamilCLONE_TEST(clone8, 0, true, true, true) 70231.106Skamil#endif 70241.106Skamil 70251.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false) 70261.106Skamil#if defined(TWAIT_HAVE_PID) 70271.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false) 70281.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false) 70291.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false) 70301.106Skamil#endif 70311.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true) 70321.106Skamil#if defined(TWAIT_HAVE_PID) 70331.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true) 70341.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true) 70351.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true) 70361.106Skamil#endif 70371.106Skamil 70381.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false) 70391.106Skamil#if defined(TWAIT_HAVE_PID) 70401.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false) 70411.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false) 70421.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false) 70431.106Skamil#endif 70441.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true) 70451.106Skamil#if defined(TWAIT_HAVE_PID) 70461.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true) 70471.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true) 70481.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true) 70491.106Skamil#endif 70501.106Skamil 70511.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false) 70521.106Skamil#if defined(TWAIT_HAVE_PID) 70531.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false) 70541.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false) 70551.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false) 70561.106Skamil#endif 70571.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true) 70581.106Skamil#if defined(TWAIT_HAVE_PID) 70591.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true) 70601.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true) 70611.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true) 70621.106Skamil#endif 70631.106Skamil 70641.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false) 70651.106Skamil#if defined(TWAIT_HAVE_PID) 70661.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false) 70671.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false) 70681.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false) 70691.106Skamil#endif 70701.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true) 70711.106Skamil#if defined(TWAIT_HAVE_PID) 70721.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true) 70731.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true) 70741.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true) 70751.106Skamil#endif 70761.106Skamil 70771.110Skamil#if TEST_VFORK_ENABLED 70781.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false) 70791.106Skamil#if defined(TWAIT_HAVE_PID) 70801.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false) 70811.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false) 70821.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false) 70831.106Skamil#endif 70841.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true) 70851.106Skamil#if defined(TWAIT_HAVE_PID) 70861.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true) 70871.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true) 70881.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true) 70891.106Skamil#endif 70901.110Skamil#endif 70911.106Skamil 70921.106Skamil/// ---------------------------------------------------------------------------- 70931.106Skamil 70941.106Skamil#if defined(TWAIT_HAVE_PID) 70951.103Skamilstatic void 70961.106Skamilclone_body2(int flags, bool masked, bool ignored) 70971.103Skamil{ 70981.103Skamil const int exitval = 5; 70991.103Skamil const int exitval2 = 15; 71001.103Skamil const int sigval = SIGSTOP; 71011.103Skamil pid_t child, child2 = 0, wpid; 71021.103Skamil#if defined(TWAIT_HAVE_STATUS) 71031.103Skamil int status; 71041.103Skamil#endif 71051.103Skamil ptrace_state_t state; 71061.103Skamil const int slen = sizeof(state); 71071.103Skamil ptrace_event_t event; 71081.103Skamil const int elen = sizeof(event); 71091.103Skamil struct sigaction sa; 71101.103Skamil struct ptrace_siginfo info; 71111.103Skamil sigset_t intmask; 71121.103Skamil struct kinfo_proc2 kp; 71131.103Skamil size_t len = sizeof(kp); 71141.103Skamil 71151.103Skamil int name[6]; 71161.103Skamil const size_t namelen = __arraycount(name); 71171.103Skamil ki_sigset_t kp_sigmask; 71181.103Skamil ki_sigset_t kp_sigignore; 71191.103Skamil 71201.103Skamil const size_t stack_size = 1024 * 1024; 71211.103Skamil void *stack, *stack_base; 71221.103Skamil 71231.103Skamil stack = malloc(stack_size); 71241.103Skamil ATF_REQUIRE(stack != NULL); 71251.103Skamil 71261.103Skamil#ifdef __MACHINE_STACK_GROWS_UP 71271.103Skamil stack_base = stack; 71281.103Skamil#else 71291.103Skamil stack_base = (char *)stack + stack_size; 71301.103Skamil#endif 71311.103Skamil 71321.103Skamil SYSCALL_REQUIRE((child = fork()) != -1); 71331.103Skamil if (child == 0) { 71341.103Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 71351.103Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 71361.103Skamil 71371.103Skamil if (masked) { 71381.103Skamil sigemptyset(&intmask); 71391.103Skamil sigaddset(&intmask, SIGTRAP); 71401.103Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 71411.103Skamil } 71421.103Skamil 71431.103Skamil if (ignored) { 71441.103Skamil memset(&sa, 0, sizeof(sa)); 71451.103Skamil sa.sa_handler = SIG_IGN; 71461.103Skamil sigemptyset(&sa.sa_mask); 71471.103Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 71481.103Skamil } 71491.103Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 71501.103Skamil FORKEE_ASSERT(raise(sigval) == 0); 71511.103Skamil 71521.103Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 71531.103Skamil flags); 71541.103Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 71551.103Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 71561.103Skamil 71571.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 71581.103Skamil child2); 71591.103Skamil 71601.103Skamil // XXX WALLSIG? 71611.103Skamil FORKEE_REQUIRE_SUCCESS 71621.103Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 71631.103Skamil 71641.103Skamil forkee_status_exited(status, exitval2); 71651.103Skamil 71661.103Skamil DPRINTF("Before exiting of the child process\n"); 71671.103Skamil _exit(exitval); 71681.103Skamil } 71691.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 71701.103Skamil 71711.103Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 71721.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 71731.103Skamil 71741.103Skamil validate_status_stopped(status, sigval); 71751.103Skamil 71761.103Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 71771.103Skamil SYSCALL_REQUIRE( 71781.103Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 71791.103Skamil 71801.103Skamil DPRINTF("Before checking siginfo_t\n"); 71811.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 71821.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 71831.103Skamil 71841.103Skamil name[0] = CTL_KERN, 71851.103Skamil name[1] = KERN_PROC2, 71861.103Skamil name[2] = KERN_PROC_PID; 71871.103Skamil name[3] = child; 71881.103Skamil name[4] = sizeof(kp); 71891.103Skamil name[5] = 1; 71901.103Skamil 71911.103Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 71921.103Skamil 71931.103Skamil if (masked) 71941.103Skamil kp_sigmask = kp.p_sigmask; 71951.103Skamil 71961.103Skamil if (ignored) 71971.103Skamil kp_sigignore = kp.p_sigignore; 71981.103Skamil 71991.103Skamil DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in " 72001.103Skamil "EVENT_MASK for the child %d\n", child); 72011.103Skamil event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE; 72021.103Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 72031.103Skamil 72041.103Skamil DPRINTF("Before resuming the child process where it left off and " 72051.103Skamil "without signal to be sent\n"); 72061.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 72071.103Skamil 72081.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 72091.103Skamil child); 72101.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 72111.103Skamil child); 72121.103Skamil 72131.103Skamil validate_status_stopped(status, SIGTRAP); 72141.103Skamil 72151.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 72161.103Skamil 72171.103Skamil if (masked) { 72181.103Skamil DPRINTF("kp_sigmask=" 72191.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72201.103Skamil PRIx32 "\n", 72211.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 72221.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 72231.103Skamil 72241.103Skamil DPRINTF("kp.p_sigmask=" 72251.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72261.103Skamil PRIx32 "\n", 72271.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 72281.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 72291.103Skamil 72301.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 72311.103Skamil sizeof(kp_sigmask))); 72321.103Skamil } 72331.103Skamil 72341.103Skamil if (ignored) { 72351.103Skamil DPRINTF("kp_sigignore=" 72361.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72371.103Skamil PRIx32 "\n", 72381.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 72391.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 72401.103Skamil 72411.103Skamil DPRINTF("kp.p_sigignore=" 72421.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72431.103Skamil PRIx32 "\n", 72441.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 72451.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 72461.103Skamil 72471.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 72481.103Skamil sizeof(kp_sigignore))); 72491.103Skamil } 72501.103Skamil 72511.103Skamil SYSCALL_REQUIRE( 72521.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 72531.103Skamil DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event, 72541.103Skamil child2); 72551.103Skamil if (!(flags & CLONE_VFORK)) { 72561.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 72571.103Skamil PTRACE_FORK); 72581.103Skamil } else { 72591.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 72601.103Skamil PTRACE_VFORK); 72611.103Skamil } 72621.103Skamil 72631.103Skamil child2 = state.pe_other_pid; 72641.103Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 72651.103Skamil 72661.103Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 72671.103Skamil "%d\n", TWAIT_FNAME, child2, child); 72681.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 72691.103Skamil child2); 72701.103Skamil 72711.103Skamil validate_status_stopped(status, SIGTRAP); 72721.103Skamil 72731.103Skamil name[3] = child2; 72741.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 72751.103Skamil 72761.103Skamil if (masked) { 72771.103Skamil DPRINTF("kp_sigmask=" 72781.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72791.103Skamil PRIx32 "\n", 72801.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 72811.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 72821.103Skamil 72831.103Skamil DPRINTF("kp.p_sigmask=" 72841.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72851.103Skamil PRIx32 "\n", 72861.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 72871.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 72881.103Skamil 72891.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 72901.103Skamil sizeof(kp_sigmask))); 72911.103Skamil } 72921.103Skamil 72931.103Skamil if (ignored) { 72941.103Skamil DPRINTF("kp_sigignore=" 72951.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72961.103Skamil PRIx32 "\n", 72971.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 72981.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 72991.103Skamil 73001.103Skamil DPRINTF("kp.p_sigignore=" 73011.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73021.103Skamil PRIx32 "\n", 73031.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 73041.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 73051.103Skamil 73061.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 73071.103Skamil sizeof(kp_sigignore))); 73081.103Skamil } 73091.103Skamil 73101.103Skamil SYSCALL_REQUIRE( 73111.103Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 73121.103Skamil if (!(flags & CLONE_VFORK)) { 73131.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 73141.103Skamil PTRACE_FORK); 73151.103Skamil } else { 73161.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 73171.103Skamil PTRACE_VFORK); 73181.103Skamil } 73191.103Skamil 73201.103Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 73211.103Skamil 73221.103Skamil DPRINTF("Before resuming the forkee process where it left off " 73231.103Skamil "and without signal to be sent\n"); 73241.103Skamil SYSCALL_REQUIRE( 73251.103Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 73261.103Skamil 73271.103Skamil DPRINTF("Before resuming the child process where it left off " 73281.103Skamil "and without signal to be sent\n"); 73291.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 73301.103Skamil 73311.103Skamil if (flags & CLONE_VFORK) { 73321.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 73331.103Skamil child); 73341.103Skamil TWAIT_REQUIRE_SUCCESS( 73351.103Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 73361.103Skamil 73371.103Skamil validate_status_stopped(status, SIGTRAP); 73381.103Skamil 73391.103Skamil name[3] = child; 73401.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 73411.103Skamil 73421.103Skamil /* 73431.103Skamil * SIGCHLD is now pending in the signal queue and 73441.103Skamil * the kernel presents it to userland as a masked signal. 73451.103Skamil */ 73461.103Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 73471.103Skamil 73481.103Skamil if (masked) { 73491.103Skamil DPRINTF("kp_sigmask=" 73501.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73511.103Skamil PRIx32 "\n", 73521.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 73531.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 73541.103Skamil 73551.103Skamil DPRINTF("kp.p_sigmask=" 73561.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73571.103Skamil PRIx32 "\n", 73581.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 73591.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 73601.103Skamil 73611.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 73621.103Skamil sizeof(kp_sigmask))); 73631.103Skamil } 73641.103Skamil 73651.103Skamil if (ignored) { 73661.103Skamil DPRINTF("kp_sigignore=" 73671.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73681.103Skamil PRIx32 "\n", 73691.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 73701.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 73711.103Skamil 73721.103Skamil DPRINTF("kp.p_sigignore=" 73731.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 73741.103Skamil PRIx32 "\n", 73751.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 73761.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 73771.103Skamil 73781.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 73791.103Skamil sizeof(kp_sigignore))); 73801.103Skamil } 73811.103Skamil 73821.103Skamil SYSCALL_REQUIRE( 73831.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 73841.103Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 73851.103Skamil 73861.103Skamil child2 = state.pe_other_pid; 73871.103Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 73881.103Skamil child2); 73891.103Skamil 73901.103Skamil DPRINTF("Before resuming the child process where it left off " 73911.103Skamil "and without signal to be sent\n"); 73921.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 73931.103Skamil } 73941.103Skamil 73951.103Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 73961.103Skamil "\n", TWAIT_FNAME); 73971.103Skamil TWAIT_REQUIRE_SUCCESS( 73981.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 73991.103Skamil 74001.103Skamil validate_status_exited(status, exitval2); 74011.103Skamil 74021.103Skamil DPRINTF("Before calling %s() for the forkee - expected no " 74031.103Skamil "process\n", TWAIT_FNAME); 74041.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 74051.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 74061.103Skamil 74071.103Skamil DPRINTF("Before calling %s() for the child - expected stopped " 74081.103Skamil "SIGCHLD\n", TWAIT_FNAME); 74091.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74101.103Skamil 74111.103Skamil validate_status_stopped(status, SIGCHLD); 74121.103Skamil 74131.103Skamil DPRINTF("Before resuming the child process where it left off and " 74141.103Skamil "without signal to be sent\n"); 74151.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 74161.103Skamil 74171.103Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 74181.103Skamil TWAIT_FNAME); 74191.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74201.103Skamil 74211.103Skamil validate_status_exited(status, exitval); 74221.103Skamil 74231.103Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 74241.103Skamil TWAIT_FNAME); 74251.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 74261.103Skamil} 74271.103Skamil 74281.106Skamil#define CLONE_TEST2(name,flags,masked,ignored) \ 74291.103SkamilATF_TC(name); \ 74301.103SkamilATF_TC_HEAD(name, tc) \ 74311.103Skamil{ \ 74321.103Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\ 74331.103Skamil " regardless of signal %s%s", \ 74341.103Skamil #flags, masked ? "masked" : "", ignored ? "ignored" : ""); \ 74351.103Skamil} \ 74361.103Skamil \ 74371.103SkamilATF_TC_BODY(name, tc) \ 74381.103Skamil{ \ 74391.103Skamil \ 74401.106Skamil clone_body2(flags, masked, ignored); \ 74411.103Skamil} 74421.103Skamil 74431.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false) 74441.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true) 74451.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false) 74461.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true) 74471.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false) 74481.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true) 74491.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false) 74501.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true) 74511.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX 74521.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true) // XXX 74531.110Skamil#if TEST_VFORK_ENABLED 74541.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false) 74551.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true) 74561.103Skamil#endif 74571.110Skamil#endif 74581.103Skamil 74591.103Skamil/// ---------------------------------------------------------------------------- 74601.103Skamil 74611.111Skamil#if TEST_VFORK_ENABLED 74621.107Skamil#if defined(TWAIT_HAVE_PID) 74631.107Skamilstatic void 74641.107Skamiltraceme_vfork_clone_body(int flags) 74651.107Skamil{ 74661.107Skamil const int exitval = 5; 74671.107Skamil const int exitval2 = 15; 74681.107Skamil pid_t child, child2 = 0, wpid; 74691.107Skamil#if defined(TWAIT_HAVE_STATUS) 74701.107Skamil int status; 74711.107Skamil#endif 74721.107Skamil 74731.107Skamil const size_t stack_size = 1024 * 1024; 74741.107Skamil void *stack, *stack_base; 74751.107Skamil 74761.107Skamil stack = malloc(stack_size); 74771.107Skamil ATF_REQUIRE(stack != NULL); 74781.107Skamil 74791.107Skamil#ifdef __MACHINE_STACK_GROWS_UP 74801.107Skamil stack_base = stack; 74811.107Skamil#else 74821.107Skamil stack_base = (char *)stack + stack_size; 74831.107Skamil#endif 74841.107Skamil 74851.107Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 74861.107Skamil if (child == 0) { 74871.107Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 74881.107Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 74891.107Skamil 74901.107Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 74911.107Skamil flags); 74921.107Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 74931.107Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 74941.107Skamil 74951.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 74961.107Skamil child2); 74971.107Skamil 74981.107Skamil // XXX WALLSIG? 74991.107Skamil FORKEE_REQUIRE_SUCCESS 75001.107Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 75011.107Skamil 75021.107Skamil forkee_status_exited(status, exitval2); 75031.107Skamil 75041.107Skamil DPRINTF("Before exiting of the child process\n"); 75051.107Skamil _exit(exitval); 75061.107Skamil } 75071.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 75081.107Skamil 75091.107Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 75101.107Skamil TWAIT_FNAME); 75111.107Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75121.107Skamil 75131.107Skamil validate_status_exited(status, exitval); 75141.107Skamil 75151.107Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 75161.107Skamil TWAIT_FNAME); 75171.107Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 75181.107Skamil} 75191.107Skamil 75201.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags) \ 75211.107SkamilATF_TC(name); \ 75221.107SkamilATF_TC_HEAD(name, tc) \ 75231.107Skamil{ \ 75241.107Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is " \ 75251.107Skamil "handled correctly with vfork(2)ed tracer", \ 75261.107Skamil #flags); \ 75271.107Skamil} \ 75281.107Skamil \ 75291.107SkamilATF_TC_BODY(name, tc) \ 75301.107Skamil{ \ 75311.107Skamil \ 75321.107Skamil traceme_vfork_clone_body(flags); \ 75331.107Skamil} 75341.107Skamil 75351.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0) 75361.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM) 75371.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS) 75381.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES) 75391.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND) // XXX 75401.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK) 75411.107Skamil#endif 75421.110Skamil#endif 75431.107Skamil 75441.107Skamil/// ---------------------------------------------------------------------------- 75451.107Skamil 75461.122Skamilstatic void 75471.122Skamiluser_va0_disable(int operation) 75481.122Skamil{ 75491.122Skamil pid_t child, wpid; 75501.122Skamil#if defined(TWAIT_HAVE_STATUS) 75511.122Skamil int status; 75521.122Skamil#endif 75531.122Skamil const int sigval = SIGSTOP; 75541.122Skamil int rv; 75551.122Skamil 75561.122Skamil struct ptrace_siginfo info; 75571.122Skamil 75581.122Skamil if (get_user_va0_disable() == 0) 75591.122Skamil atf_tc_skip("vm.user_va0_disable is set to 0"); 75601.122Skamil 75611.122Skamil memset(&info, 0, sizeof(info)); 75621.122Skamil 75631.122Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 75641.122Skamil SYSCALL_REQUIRE((child = fork()) != -1); 75651.122Skamil if (child == 0) { 75661.122Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 75671.122Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 75681.122Skamil 75691.122Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 75701.122Skamil FORKEE_ASSERT(raise(sigval) == 0); 75711.122Skamil 75721.122Skamil /* NOTREACHED */ 75731.122Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 75741.122Skamil __unreachable(); 75751.122Skamil } 75761.122Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 75771.122Skamil 75781.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75791.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75801.122Skamil 75811.122Skamil validate_status_stopped(status, sigval); 75821.122Skamil 75831.122Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 75841.122Skamil "child\n"); 75851.122Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 75861.122Skamil sizeof(info)) != -1); 75871.122Skamil 75881.122Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 75891.122Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 75901.122Skamil "si_errno=%#x\n", 75911.122Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 75921.122Skamil info.psi_siginfo.si_errno); 75931.122Skamil 75941.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 75951.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 75961.122Skamil 75971.122Skamil DPRINTF("Before resuming the child process in PC=0x0 " 75981.122Skamil "and without signal to be sent\n"); 75991.122Skamil errno = 0; 76001.122Skamil rv = ptrace(operation, child, (void *)0, 0); 76011.122Skamil ATF_REQUIRE_EQ(errno, EINVAL); 76021.122Skamil ATF_REQUIRE_EQ(rv, -1); 76031.122Skamil 76041.122Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 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 validate_status_signaled(status, SIGKILL, 0); 76091.122Skamil 76101.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 76111.122Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 76121.122Skamil} 76131.122Skamil 76141.122Skamil#define USER_VA0_DISABLE(test, operation) \ 76151.122SkamilATF_TC(test); \ 76161.122SkamilATF_TC_HEAD(test, tc) \ 76171.122Skamil{ \ 76181.122Skamil atf_tc_set_md_var(tc, "descr", \ 76191.122Skamil "Verify behavior of " #operation " with PC set to 0x0"); \ 76201.122Skamil} \ 76211.122Skamil \ 76221.122SkamilATF_TC_BODY(test, tc) \ 76231.122Skamil{ \ 76241.122Skamil \ 76251.122Skamil user_va0_disable(operation); \ 76261.122Skamil} 76271.122Skamil 76281.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE) 76291.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL) 76301.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH) 76311.122Skamil 76321.122Skamil/// ---------------------------------------------------------------------------- 76331.122Skamil 76341.1Skamil#include "t_ptrace_amd64_wait.h" 76351.1Skamil#include "t_ptrace_i386_wait.h" 76361.1Skamil#include "t_ptrace_x86_wait.h" 76371.1Skamil 76381.1SkamilATF_TP_ADD_TCS(tp) 76391.1Skamil{ 76401.1Skamil setvbuf(stdout, NULL, _IONBF, 0); 76411.1Skamil setvbuf(stderr, NULL, _IONBF, 0); 76421.33Skamil 76431.36Skamil ATF_TP_ADD_TC(tp, traceme_raise1); 76441.33Skamil ATF_TP_ADD_TC(tp, traceme_raise2); 76451.33Skamil ATF_TP_ADD_TC(tp, traceme_raise3); 76461.33Skamil ATF_TP_ADD_TC(tp, traceme_raise4); 76471.33Skamil ATF_TP_ADD_TC(tp, traceme_raise5); 76481.85Skamil ATF_TP_ADD_TC(tp, traceme_raise6); 76491.85Skamil ATF_TP_ADD_TC(tp, traceme_raise7); 76501.85Skamil ATF_TP_ADD_TC(tp, traceme_raise8); 76511.85Skamil ATF_TP_ADD_TC(tp, traceme_raise9); 76521.85Skamil ATF_TP_ADD_TC(tp, traceme_raise10); 76531.33Skamil 76541.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1); 76551.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2); 76561.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3); 76571.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4); 76581.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5); 76591.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6); 76601.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7); 76611.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8); 76621.87Skamil 76631.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1); 76641.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2); 76651.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3); 76661.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4); 76671.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5); 76681.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6); 76691.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7); 76701.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8); 76711.86Skamil 76721.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_trap); 76731.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_segv); 76741.71Skamil ATF_TP_ADD_TC(tp, traceme_crash_ill); 76751.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_fpe); 76761.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_bus); 76771.59Skamil 76781.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap); 76791.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv); 76801.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill); 76811.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe); 76821.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus); 76831.88Skamil 76841.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap); 76851.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv); 76861.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill); 76871.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe); 76881.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus); 76891.88Skamil 76901.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1); 76911.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2); 76921.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3); 76931.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4); 76941.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5); 76951.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6); 76961.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7); 76971.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8); 76981.50Skamil 76991.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1); 77001.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2); 77011.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3); 77021.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4); 77031.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5); 77041.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6); 77051.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7); 77061.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8); 77071.50Skamil 77081.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1); 77091.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2); 77101.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3); 77111.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4); 77121.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5); 77131.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6); 77141.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7); 77151.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8); 77161.50Skamil 77171.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1); 77181.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2); 77191.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3); 77201.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4); 77211.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5); 77221.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6); 77231.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7); 77241.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8); 77251.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9); 77261.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10); 77271.1Skamil 77281.37Skamil ATF_TP_ADD_TC(tp, traceme_pid1_parent); 77291.37Skamil 77301.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise1); 77311.46Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise2); 77321.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise3); 77331.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise4); 77341.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise5); 77351.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise6); 77361.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise7); 77371.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise8); 77381.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise9); 77391.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise10); 77401.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise11); 77411.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise12); 77421.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise13); 77431.40Skamil 77441.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap); 77451.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv); 77461.71Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill); 77471.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe); 77481.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus); 77491.41Skamil 77501.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap); 77511.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv); 77521.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill); 77531.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe); 77541.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus); 77551.92Skamil 77561.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap); 77571.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv); 77581.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill); 77591.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe); 77601.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus); 77611.92Skamil 77621.43Skamil ATF_TP_ADD_TC(tp, traceme_vfork_exec); 77631.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec); 77641.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec); 77651.43Skamil 77661.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap); 77671.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv); 77681.71Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill); 77691.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe); 77701.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus); 77711.59Skamil 77721.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77731.94Skamil unrelated_tracer_sees_signalmasked_crash_trap); 77741.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77751.94Skamil unrelated_tracer_sees_signalmasked_crash_segv); 77761.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77771.94Skamil unrelated_tracer_sees_signalmasked_crash_ill); 77781.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77791.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe); 77801.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77811.94Skamil unrelated_tracer_sees_signalmasked_crash_bus); 77821.94Skamil 77831.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77841.94Skamil unrelated_tracer_sees_signalignored_crash_trap); 77851.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77861.94Skamil unrelated_tracer_sees_signalignored_crash_segv); 77871.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77881.94Skamil unrelated_tracer_sees_signalignored_crash_ill); 77891.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77901.94Skamil unrelated_tracer_sees_signalignored_crash_fpe); 77911.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77921.94Skamil unrelated_tracer_sees_signalignored_crash_bus); 77931.94Skamil 77941.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent); 77951.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates); 77961.61Skre ATF_TP_ADD_TC_HAVE_PID(tp, 77971.61Skre unrelated_tracer_sees_terminaton_before_the_parent); 77981.67Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process); 77991.51Skamil 78001.51Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_child); 78011.66Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child); 78021.51Skamil 78031.51Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_parent); 78041.65Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent); 78051.51Skamil 78061.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 78071.51Skamil tracee_sees_its_original_parent_getppid); 78081.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 78091.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2); 78101.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 78111.51Skamil tracee_sees_its_original_parent_procfs_status); 78121.1Skamil 78131.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_empty); 78141.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_fork); 78151.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork); 78161.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done); 78171.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create); 78181.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit); 78191.125Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_posix_spawn); 78201.1Skamil 78211.31Skamil ATF_TP_ADD_TC(tp, fork1); 78221.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork2); 78231.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork3); 78241.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork4); 78251.31Skamil ATF_TP_ADD_TC(tp, fork5); 78261.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork6); 78271.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork7); 78281.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork8); 78291.125Skamil ATF_TP_ADD_TC(tp, fork9); 78301.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork10); 78311.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork11); 78321.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork12); 78331.125Skamil ATF_TP_ADD_TC(tp, fork13); 78341.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork14); 78351.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork15); 78361.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork16); 78371.31Skamil 78381.109Skamil#if TEST_VFORK_ENABLED 78391.31Skamil ATF_TP_ADD_TC(tp, vfork1); 78401.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork2); 78411.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork3); 78421.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork4); 78431.31Skamil ATF_TP_ADD_TC(tp, vfork5); 78441.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork6); 78451.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork7); 78461.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork8); 78471.125Skamil ATF_TP_ADD_TC(tp, vfork9); 78481.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork10); 78491.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork11); 78501.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork12); 78511.125Skamil ATF_TP_ADD_TC(tp, vfork13); 78521.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork14); 78531.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork15); 78541.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork16); 78551.116Skamil#endif 78561.1Skamil 78571.124Skamil ATF_TP_ADD_TC(tp, posix_spawn1); 78581.125Skamil ATF_TP_ADD_TC(tp, posix_spawn2); 78591.125Skamil ATF_TP_ADD_TC(tp, posix_spawn3); 78601.125Skamil ATF_TP_ADD_TC(tp, posix_spawn4); 78611.124Skamil ATF_TP_ADD_TC(tp, posix_spawn5); 78621.125Skamil ATF_TP_ADD_TC(tp, posix_spawn6); 78631.125Skamil ATF_TP_ADD_TC(tp, posix_spawn7); 78641.125Skamil ATF_TP_ADD_TC(tp, posix_spawn8); 78651.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn9); 78661.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn10); 78671.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn11); 78681.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn12); 78691.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn13); 78701.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn14); 78711.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn15); 78721.125Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn16); 78731.124Skamil 78741.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_detach_spawner); 78751.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_detach_forker); 78761.116Skamil#if TEST_VFORK_ENABLED 78771.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforker); 78781.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforkerdone); 78791.116Skamil#endif 78801.126Skamil 78811.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_kill_spawner); 78821.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_kill_forker); 78831.116Skamil#if TEST_VFORK_ENABLED 78841.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforker); 78851.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforkerdone); 78861.116Skamil#endif 78871.116Skamil 78881.116Skamil#if TEST_VFORK_ENABLED 78891.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_fork); 78901.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_vfork); 78911.109Skamil#endif 78921.108Skamil 78931.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8); 78941.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16); 78951.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32); 78961.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64); 78971.54Skamil 78981.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8); 78991.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16); 79001.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32); 79011.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64); 79021.54Skamil 79031.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8); 79041.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16); 79051.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32); 79061.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64); 79071.54Skamil 79081.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8); 79091.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16); 79101.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32); 79111.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64); 79121.54Skamil 79131.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d); 79141.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i); 79151.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d); 79161.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i); 79171.54Skamil 79181.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text); 79191.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text); 79201.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text); 79211.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text); 79221.54Skamil 79231.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text); 79241.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text); 79251.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text); 79261.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text); 79271.54Skamil 79281.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text); 79291.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text); 79301.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text); 79311.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text); 79321.54Skamil 79331.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text); 79341.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text); 79351.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text); 79361.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text); 79371.54Skamil 79381.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text); 79391.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text); 79401.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text); 79411.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text); 79421.1Skamil 79431.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv); 79441.1Skamil 79451.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i); 79461.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d); 79471.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i); 79481.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d); 79491.101Skamil 79501.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i); 79511.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d); 79521.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i); 79531.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d); 79541.101Skamil 79551.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv); 79561.101Skamil 79571.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i); 79581.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d); 79591.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i); 79601.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d); 79611.115Skamil 79621.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i); 79631.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d); 79641.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i); 79651.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d); 79661.115Skamil 79671.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1); 79681.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2); 79691.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3); 79701.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4); 79711.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5); 79721.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6); 79731.1Skamil 79741.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1); 79751.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2); 79761.1Skamil 79771.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step1); 79781.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step2); 79791.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step3); 79801.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step4); 79811.1Skamil 79821.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep1); 79831.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep2); 79841.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep3); 79851.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep4); 79861.2Skamil 79871.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked); 79881.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored); 79891.95Skamil 79901.1Skamil ATF_TP_ADD_TC(tp, kill1); 79911.1Skamil ATF_TP_ADD_TC(tp, kill2); 79921.75Skamil ATF_TP_ADD_TC(tp, kill3); 79931.1Skamil 79941.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0); 79951.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1); 79961.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2); 79971.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3); 79981.77Skamil 79991.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0); 80001.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1); 80011.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2); 80021.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3); 80031.1Skamil 80041.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_unmodified); 80051.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_faked); 80061.79Skamil 80071.82Skamil ATF_TP_ADD_TC(tp, traceme_exec); 80081.97Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_exec); 80091.97Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_exec); 80101.1Skamil 80111.119Skamil ATF_TP_ADD_TC(tp, trace_thread_nolwpevents); 80121.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpexit); 80131.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate); 80141.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit); 80151.1Skamil 80161.84Skamil ATF_TP_ADD_TC(tp, signal_mask_unrelated); 80171.84Skamil 80181.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalmasked); 80191.126Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn_singalignored); 80201.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked); 80211.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored); 80221.109Skamil#if TEST_VFORK_ENABLED 80231.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked); 80241.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored); 80251.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked); 80261.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored); 80271.109Skamil#endif 80281.99Skamil 80291.1Skamil ATF_TP_ADD_TC(tp, signal9); 80301.1Skamil ATF_TP_ADD_TC(tp, signal10); 80311.1Skamil 80321.1Skamil ATF_TP_ADD_TC(tp, suspend1); 80331.1Skamil ATF_TP_ADD_TC(tp, suspend2); 80341.1Skamil 80351.1Skamil ATF_TP_ADD_TC(tp, resume1); 80361.1Skamil 80371.1Skamil ATF_TP_ADD_TC(tp, syscall1); 80381.1Skamil 80391.1Skamil ATF_TP_ADD_TC(tp, syscallemu1); 80401.1Skamil 80411.106Skamil ATF_TP_ADD_TC(tp, clone1); 80421.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone2); 80431.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone3); 80441.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone4); 80451.106Skamil ATF_TP_ADD_TC(tp, clone5); 80461.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone6); 80471.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone7); 80481.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone8); 80491.106Skamil 80501.106Skamil ATF_TP_ADD_TC(tp, clone_vm1); 80511.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2); 80521.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3); 80531.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4); 80541.106Skamil ATF_TP_ADD_TC(tp, clone_vm5); 80551.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6); 80561.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7); 80571.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8); 80581.106Skamil 80591.106Skamil ATF_TP_ADD_TC(tp, clone_fs1); 80601.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2); 80611.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3); 80621.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4); 80631.106Skamil ATF_TP_ADD_TC(tp, clone_fs5); 80641.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6); 80651.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7); 80661.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8); 80671.106Skamil 80681.106Skamil ATF_TP_ADD_TC(tp, clone_files1); 80691.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2); 80701.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3); 80711.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4); 80721.106Skamil ATF_TP_ADD_TC(tp, clone_files5); 80731.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6); 80741.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7); 80751.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8); 80761.106Skamil 80771.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand1); // XXX 80781.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX 80791.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX 80801.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX 80811.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand5); // XXX 80821.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX 80831.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX 80841.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX 80851.106Skamil 80861.109Skamil#if TEST_VFORK_ENABLED 80871.106Skamil ATF_TP_ADD_TC(tp, clone_vfork1); 80881.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2); 80891.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3); 80901.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4); 80911.106Skamil ATF_TP_ADD_TC(tp, clone_vfork5); 80921.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6); 80931.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7); 80941.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8); 80951.109Skamil#endif 80961.106Skamil 80971.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored); 80981.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked); 80991.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored); 81001.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked); 81011.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored); 81021.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked); 81031.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored); 81041.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked); 81051.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX 81061.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX 81071.109Skamil#if TEST_VFORK_ENABLED 81081.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored); 81091.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked); 81101.109Skamil#endif 81111.103Skamil 81121.109Skamil#if TEST_VFORK_ENABLED 81131.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone); 81141.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm); 81151.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs); 81161.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files); 81171.107Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX 81181.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork); 81191.109Skamil#endif 81201.107Skamil 81211.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue); 81221.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall); 81231.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach); 81241.122Skamil 81251.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64(); 81261.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_I386(); 81271.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_X86(); 81281.1Skamil 81291.1Skamil return atf_no_error(); 81301.1Skamil} 8131