t_ptrace_wait.c revision 1.124
11.123Skamil/* $NetBSD: t_ptrace_wait.c,v 1.124 2019/06/10 22:16: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.123Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.124 2019/06/10 22:16: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.109Skamil#define TEST_VFORK_ENABLED 0 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.1Skamil ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); 29511.1Skamil 29521.13Schristos DPRINTF("Before resuming the child process where it left off and " 29531.1Skamil "without signal to be sent\n"); 29541.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 29551.1Skamil 29561.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29571.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29581.1Skamil 29591.1Skamil validate_status_exited(status, exitval); 29601.1Skamil 29611.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29621.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 29631.1Skamil} 29641.1Skamil 29651.61Skre#define EVENTMASK_PRESERVED(test, event) \ 29661.61SkreATF_TC(test); \ 29671.61SkreATF_TC_HEAD(test, tc) \ 29681.61Skre{ \ 29691.61Skre atf_tc_set_md_var(tc, "descr", \ 29701.61Skre "Verify that eventmask " #event " is preserved"); \ 29711.61Skre} \ 29721.61Skre \ 29731.61SkreATF_TC_BODY(test, tc) \ 29741.61Skre{ \ 29751.61Skre \ 29761.61Skre eventmask_preserved(event); \ 29771.1Skamil} 29781.1Skamil 29791.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0) 29801.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK) 29811.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK) 29821.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE) 29831.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE) 29841.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT) 29851.1Skamil 29861.53Skamil/// ---------------------------------------------------------------------------- 29871.1Skamil 29881.28Skamilstatic void 29891.124Skamilfork_body(pid_t (*fn)(void), bool spawn, bool trackfork, bool trackvfork, 29901.105Skamil bool trackvforkdone) 29911.1Skamil{ 29921.1Skamil const int exitval = 5; 29931.1Skamil const int exitval2 = 15; 29941.1Skamil const int sigval = SIGSTOP; 29951.31Skamil pid_t child, child2 = 0, wpid; 29961.1Skamil#if defined(TWAIT_HAVE_STATUS) 29971.1Skamil int status; 29981.1Skamil#endif 29991.1Skamil ptrace_state_t state; 30001.1Skamil const int slen = sizeof(state); 30011.1Skamil ptrace_event_t event; 30021.1Skamil const int elen = sizeof(event); 30031.1Skamil 30041.124Skamil char * const arg[] = { __UNCONST("/bin/echo"), NULL }; 30051.124Skamil 30061.124Skamil if (spawn) 30071.124Skamil atf_tc_skip("posix_spawn() is not supported"); 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.124Skamil if (spawn) { 30191.124Skamil FORKEE_ASSERT_EQ(posix_spawn(&child2, 30201.124Skamil arg[0], NULL, NULL, arg, NULL), 0); 30211.124Skamil } else if (fn == fork || fn == vfork) { 30221.124Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 30231.1Skamil 30241.124Skamil if (child2 == 0) 30251.124Skamil _exit(exitval2); 30261.124Skamil } 30271.1Skamil FORKEE_REQUIRE_SUCCESS 30281.1Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 30291.1Skamil 30301.1Skamil forkee_status_exited(status, exitval2); 30311.1Skamil 30321.13Schristos DPRINTF("Before exiting of the child process\n"); 30331.1Skamil _exit(exitval); 30341.1Skamil } 30351.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 30361.1Skamil 30371.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 30381.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 30391.1Skamil 30401.1Skamil validate_status_stopped(status, sigval); 30411.1Skamil 30421.30Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 30431.61Skre trackfork ? "|PTRACE_FORK" : "", 30441.61Skre trackvfork ? "|PTRACE_VFORK" : "", 30451.61Skre trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 30461.30Skamil event.pe_set_event = 0; 30471.30Skamil if (trackfork) 30481.30Skamil event.pe_set_event |= PTRACE_FORK; 30491.30Skamil if (trackvfork) 30501.30Skamil event.pe_set_event |= PTRACE_VFORK; 30511.30Skamil if (trackvforkdone) 30521.30Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 30531.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 30541.1Skamil 30551.13Schristos DPRINTF("Before resuming the child process where it left off and " 30561.1Skamil "without signal to be sent\n"); 30571.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 30581.1Skamil 30591.29Skamil#if defined(TWAIT_HAVE_PID) 30601.31Skamil if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) { 30611.29Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 30621.61Skre child); 30631.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 30641.61Skre child); 30651.1Skamil 30661.29Skamil validate_status_stopped(status, SIGTRAP); 30671.1Skamil 30681.61Skre SYSCALL_REQUIRE( 30691.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 30701.31Skamil if (trackfork && fn == fork) { 30711.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 30721.30Skamil PTRACE_FORK); 30731.30Skamil } 30741.31Skamil if (trackvfork && fn == vfork) { 30751.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 30761.30Skamil PTRACE_VFORK); 30771.30Skamil } 30781.29Skamil 30791.29Skamil child2 = state.pe_other_pid; 30801.30Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 30811.29Skamil 30821.29Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 30831.61Skre "%d\n", TWAIT_FNAME, child2, child); 30841.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 30851.29Skamil child2); 30861.1Skamil 30871.29Skamil validate_status_stopped(status, SIGTRAP); 30881.1Skamil 30891.61Skre SYSCALL_REQUIRE( 30901.61Skre ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 30911.31Skamil if (trackfork && fn == fork) { 30921.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 30931.30Skamil PTRACE_FORK); 30941.30Skamil } 30951.31Skamil if (trackvfork && fn == vfork) { 30961.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 30971.30Skamil PTRACE_VFORK); 30981.30Skamil } 30991.30Skamil 31001.29Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 31011.29Skamil 31021.29Skamil DPRINTF("Before resuming the forkee process where it left off " 31031.29Skamil "and without signal to be sent\n"); 31041.61Skre SYSCALL_REQUIRE( 31051.61Skre ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 31061.29Skamil 31071.29Skamil DPRINTF("Before resuming the child process where it left off " 31081.61Skre "and without signal to be sent\n"); 31091.29Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31101.30Skamil } 31111.30Skamil#endif 31121.30Skamil 31131.31Skamil if (trackvforkdone && fn == vfork) { 31141.30Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 31151.61Skre child); 31161.61Skre TWAIT_REQUIRE_SUCCESS( 31171.61Skre wpid = TWAIT_GENERIC(child, &status, 0), child); 31181.30Skamil 31191.30Skamil validate_status_stopped(status, SIGTRAP); 31201.30Skamil 31211.61Skre SYSCALL_REQUIRE( 31221.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 31231.30Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 31241.30Skamil 31251.30Skamil child2 = state.pe_other_pid; 31261.30Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 31271.61Skre child2); 31281.30Skamil 31291.30Skamil DPRINTF("Before resuming the child process where it left off " 31301.61Skre "and without signal to be sent\n"); 31311.30Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31321.30Skamil } 31331.29Skamil 31341.30Skamil#if defined(TWAIT_HAVE_PID) 31351.31Skamil if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) { 31361.29Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 31371.61Skre "\n", TWAIT_FNAME); 31381.61Skre TWAIT_REQUIRE_SUCCESS( 31391.61Skre wpid = TWAIT_GENERIC(child2, &status, 0), child2); 31401.29Skamil 31411.29Skamil validate_status_exited(status, exitval2); 31421.29Skamil 31431.29Skamil DPRINTF("Before calling %s() for the forkee - expected no " 31441.61Skre "process\n", TWAIT_FNAME); 31451.29Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 31461.29Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 31471.29Skamil } 31481.29Skamil#endif 31491.1Skamil 31501.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 31511.1Skamil "SIGCHLD\n", TWAIT_FNAME); 31521.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31531.1Skamil 31541.1Skamil validate_status_stopped(status, SIGCHLD); 31551.1Skamil 31561.13Schristos DPRINTF("Before resuming the child process where it left off and " 31571.1Skamil "without signal to be sent\n"); 31581.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31591.1Skamil 31601.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 31611.1Skamil TWAIT_FNAME); 31621.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31631.1Skamil 31641.1Skamil validate_status_exited(status, exitval); 31651.1Skamil 31661.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 31671.1Skamil TWAIT_FNAME); 31681.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 31691.1Skamil} 31701.28Skamil 31711.124Skamil#define FORK_TEST(name,fun,spawn,tfork,tvfork,tvforkdone) \ 31721.61SkreATF_TC(name); \ 31731.61SkreATF_TC_HEAD(name, tc) \ 31741.61Skre{ \ 31751.105Skamil atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) " \ 31761.105Skamil "called with 0%s%s%s in EVENT_MASK", \ 31771.105Skamil tfork ? "|PTRACE_FORK" : "", \ 31781.105Skamil tvfork ? "|PTRACE_VFORK" : "", \ 31791.105Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 31801.61Skre} \ 31811.61Skre \ 31821.61SkreATF_TC_BODY(name, tc) \ 31831.61Skre{ \ 31841.61Skre \ 31851.124Skamil fork_body(fun, spawn, tfork, tvfork, tvforkdone); \ 31861.32Skamil} 31871.32Skamil 31881.124SkamilFORK_TEST(fork1, fork, false, false, false, false) 31891.31Skamil#if defined(TWAIT_HAVE_PID) 31901.124SkamilFORK_TEST(fork2, fork, false, true, false, false) 31911.124SkamilFORK_TEST(fork3, fork, false, false, true, false) 31921.124SkamilFORK_TEST(fork4, fork, false, true, true, false) 31931.31Skamil#endif 31941.124SkamilFORK_TEST(fork5, fork, false, false, false, true) 31951.31Skamil#if defined(TWAIT_HAVE_PID) 31961.124SkamilFORK_TEST(fork6, fork, false, true, false, true) 31971.124SkamilFORK_TEST(fork7, fork, false, false, true, true) 31981.124SkamilFORK_TEST(fork8, fork, false, true, true, true) 31991.31Skamil#endif 32001.1Skamil 32011.110Skamil#if TEST_VFORK_ENABLED 32021.124SkamilFORK_TEST(vfork1, vfork, false, false, false, false) 32031.31Skamil#if defined(TWAIT_HAVE_PID) 32041.124SkamilFORK_TEST(vfork2, vfork, false, true, false, false) 32051.124SkamilFORK_TEST(vfork3, vfork, false, false, true, false) 32061.124SkamilFORK_TEST(vfork4, vfork, false, true, true, false) 32071.31Skamil#endif 32081.124SkamilFORK_TEST(vfork5, vfork, false, false, false, true) 32091.31Skamil#if defined(TWAIT_HAVE_PID) 32101.124SkamilFORK_TEST(vfork6, vfork, false, true, false, true) 32111.124SkamilFORK_TEST(vfork7, vfork, false, false, true, true) 32121.124SkamilFORK_TEST(vfork8, vfork, false, true, true, true) 32131.31Skamil#endif 32141.110Skamil#endif 32151.31Skamil 32161.124Skamil/* It's ugly, but passing posix_spawn as 'bool' avoids function pointer cast */ 32171.124SkamilFORK_TEST(posix_spawn1, fork, true, false, false, false) 32181.124Skamil#if defined(TWAIT_HAVE_PID) 32191.124SkamilFORK_TEST(posix_spawn2, fork, true, true, false, false) 32201.124SkamilFORK_TEST(posix_spawn3, fork, true, false, true, false) 32211.124SkamilFORK_TEST(posix_spawn4, fork, true, true, true, false) 32221.124Skamil#endif 32231.124SkamilFORK_TEST(posix_spawn5, fork, true, false, false, true) 32241.124Skamil#if defined(TWAIT_HAVE_PID) 32251.124SkamilFORK_TEST(posix_spawn6, fork, true, true, false, true) 32261.124SkamilFORK_TEST(posix_spawn7, fork, true, false, true, true) 32271.124SkamilFORK_TEST(posix_spawn8, fork, true, true, true, true) 32281.124Skamil#endif 32291.124Skamil 32301.54Skamil/// ---------------------------------------------------------------------------- 32311.31Skamil 32321.116Skamil#if defined(TWAIT_HAVE_PID) 32331.116Skamilstatic void 32341.116Skamilfork_detach_forker_body(bool detachfork, bool detachvfork, 32351.116Skamil bool detachvforkdone, bool kill_process) 32361.116Skamil{ 32371.116Skamil const int exitval = 5; 32381.116Skamil const int exitval2 = 15; 32391.116Skamil const int sigval = SIGSTOP; 32401.116Skamil pid_t child, child2 = 0, wpid; 32411.116Skamil#if defined(TWAIT_HAVE_STATUS) 32421.116Skamil int status; 32431.116Skamil#endif 32441.116Skamil ptrace_state_t state; 32451.116Skamil const int slen = sizeof(state); 32461.116Skamil ptrace_event_t event; 32471.116Skamil const int elen = sizeof(event); 32481.116Skamil 32491.116Skamil pid_t (*fn)(void); 32501.116Skamil int op; 32511.116Skamil 32521.116Skamil ATF_REQUIRE((detachfork && !detachvfork && !detachvforkdone) || 32531.116Skamil (!detachfork && detachvfork && !detachvforkdone) || 32541.116Skamil (!detachfork && !detachvfork && detachvforkdone)); 32551.116Skamil 32561.116Skamil if (detachfork) 32571.116Skamil fn = fork; 32581.116Skamil else 32591.116Skamil fn = vfork; 32601.116Skamil 32611.116Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 32621.116Skamil SYSCALL_REQUIRE((child = fork()) != -1); 32631.116Skamil if (child == 0) { 32641.116Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 32651.116Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 32661.116Skamil 32671.116Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 32681.116Skamil FORKEE_ASSERT(raise(sigval) == 0); 32691.116Skamil 32701.116Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 32711.116Skamil 32721.116Skamil if (child2 == 0) 32731.116Skamil _exit(exitval2); 32741.116Skamil 32751.116Skamil FORKEE_REQUIRE_SUCCESS 32761.116Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 32771.116Skamil 32781.116Skamil forkee_status_exited(status, exitval2); 32791.116Skamil 32801.116Skamil DPRINTF("Before exiting of the child process\n"); 32811.116Skamil _exit(exitval); 32821.116Skamil } 32831.116Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 32841.116Skamil 32851.116Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 32861.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 32871.116Skamil 32881.116Skamil validate_status_stopped(status, sigval); 32891.116Skamil 32901.116Skamil DPRINTF("Set EVENT_MASK for the child %d\n", child); 32911.116Skamil event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE; 32921.116Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 32931.116Skamil 32941.116Skamil DPRINTF("Before resuming the child process where it left off and " 32951.116Skamil "without signal to be sent\n"); 32961.116Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 32971.116Skamil 32981.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child); 32991.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33001.116Skamil 33011.116Skamil validate_status_stopped(status, SIGTRAP); 33021.116Skamil 33031.116Skamil SYSCALL_REQUIRE( 33041.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 33051.116Skamil op = (fn == fork) ? PTRACE_FORK : PTRACE_VFORK; 33061.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 33071.116Skamil 33081.116Skamil child2 = state.pe_other_pid; 33091.116Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 33101.116Skamil 33111.116Skamil if (detachfork || detachvfork) 33121.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 33131.116Skamil else 33141.116Skamil op = PT_CONTINUE; 33151.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 33161.116Skamil 33171.116Skamil DPRINTF("Before calling %s() for the forkee %d of the child %d\n", 33181.116Skamil TWAIT_FNAME, child2, child); 33191.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 33201.116Skamil 33211.116Skamil validate_status_stopped(status, SIGTRAP); 33221.116Skamil 33231.116Skamil SYSCALL_REQUIRE( 33241.116Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 33251.116Skamil op = (fn == fork) ? PTRACE_FORK : PTRACE_VFORK; 33261.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 33271.116Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 33281.116Skamil 33291.116Skamil DPRINTF("Before resuming the forkee process where it left off " 33301.116Skamil "and without signal to be sent\n"); 33311.116Skamil SYSCALL_REQUIRE( 33321.116Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 33331.116Skamil 33341.116Skamil if (detachvforkdone && fn == vfork) { 33351.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 33361.116Skamil child); 33371.116Skamil TWAIT_REQUIRE_SUCCESS( 33381.116Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 33391.116Skamil 33401.116Skamil validate_status_stopped(status, SIGTRAP); 33411.116Skamil 33421.116Skamil SYSCALL_REQUIRE( 33431.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 33441.116Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 33451.116Skamil 33461.116Skamil child2 = state.pe_other_pid; 33471.116Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 33481.116Skamil child2); 33491.116Skamil 33501.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 33511.116Skamil DPRINTF("Before resuming the child process where it left off " 33521.116Skamil "and without signal to be sent\n"); 33531.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 33541.116Skamil } 33551.116Skamil 33561.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 33571.116Skamil TWAIT_FNAME); 33581.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 33591.116Skamil 33601.116Skamil validate_status_exited(status, exitval2); 33611.116Skamil 33621.116Skamil DPRINTF("Before calling %s() for the forkee - expected no process\n", 33631.116Skamil TWAIT_FNAME); 33641.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child2, &status, 0)); 33651.116Skamil 33661.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 33671.116Skamil TWAIT_FNAME); 33681.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33691.116Skamil 33701.116Skamil if (kill_process) { 33711.116Skamil validate_status_signaled(status, SIGKILL, 0); 33721.116Skamil } else { 33731.116Skamil validate_status_exited(status, exitval); 33741.116Skamil } 33751.116Skamil 33761.116Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 33771.116Skamil TWAIT_FNAME); 33781.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 33791.116Skamil} 33801.116Skamil 33811.116Skamil#define FORK_DETACH_FORKER(name,detfork,detvfork,detvforkdone,kprocess) \ 33821.116SkamilATF_TC(name); \ 33831.116SkamilATF_TC_HEAD(name, tc) \ 33841.116Skamil{ \ 33851.116Skamil atf_tc_set_md_var(tc, "descr", "Verify %s %s%s%s", \ 33861.116Skamil kprocess ? "killed" : "detached", \ 33871.116Skamil detfork ? "forker" : "", \ 33881.116Skamil detvfork ? "vforker" : "", \ 33891.116Skamil detvforkdone ? "vforker done" : ""); \ 33901.116Skamil} \ 33911.116Skamil \ 33921.116SkamilATF_TC_BODY(name, tc) \ 33931.116Skamil{ \ 33941.116Skamil \ 33951.116Skamil fork_detach_forker_body(detfork, detvfork, detvforkdone, \ 33961.116Skamil kprocess); \ 33971.116Skamil} 33981.116Skamil 33991.116SkamilFORK_DETACH_FORKER(fork_detach_forker, true, false, false, false) 34001.116Skamil#if TEST_VFORK_ENABLED 34011.116SkamilFORK_DETACH_FORKER(vfork_detach_vforker, false, true, false, false) 34021.116SkamilFORK_DETACH_FORKER(vfork_detach_vforkerdone, false, false, true, false) 34031.116Skamil#endif 34041.116SkamilFORK_DETACH_FORKER(fork_kill_forker, true, false, false, true) 34051.116Skamil#if TEST_VFORK_ENABLED 34061.116SkamilFORK_DETACH_FORKER(vfork_kill_vforker, false, true, false, true) 34071.116SkamilFORK_DETACH_FORKER(vfork_kill_vforkerdone, false, false, true, true) 34081.116Skamil#endif 34091.116Skamil#endif 34101.116Skamil 34111.116Skamil/// ---------------------------------------------------------------------------- 34121.116Skamil 34131.110Skamil#if TEST_VFORK_ENABLED 34141.108Skamilstatic void 34151.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void)) 34161.108Skamil{ 34171.108Skamil const int exitval = 5; 34181.108Skamil const int exitval2 = 15; 34191.108Skamil pid_t child, child2 = 0, wpid; 34201.108Skamil#if defined(TWAIT_HAVE_STATUS) 34211.108Skamil int status; 34221.108Skamil#endif 34231.108Skamil 34241.108Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 34251.108Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 34261.108Skamil if (child == 0) { 34271.108Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 34281.108Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 34291.108Skamil 34301.108Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 34311.108Skamil 34321.108Skamil if (child2 == 0) 34331.108Skamil _exit(exitval2); 34341.108Skamil 34351.108Skamil FORKEE_REQUIRE_SUCCESS 34361.108Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 34371.108Skamil 34381.108Skamil forkee_status_exited(status, exitval2); 34391.108Skamil 34401.108Skamil DPRINTF("Before exiting of the child process\n"); 34411.108Skamil _exit(exitval); 34421.108Skamil } 34431.108Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 34441.108Skamil 34451.108Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 34461.108Skamil TWAIT_FNAME); 34471.108Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 34481.108Skamil 34491.108Skamil validate_status_exited(status, exitval); 34501.108Skamil 34511.108Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 34521.108Skamil TWAIT_FNAME); 34531.108Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 34541.108Skamil} 34551.108Skamil 34561.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun) \ 34571.108SkamilATF_TC(name); \ 34581.108SkamilATF_TC_HEAD(name, tc) \ 34591.108Skamil{ \ 34601.108Skamil atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) " \ 34611.108Skamil "called from vfork(2)ed child"); \ 34621.108Skamil} \ 34631.108Skamil \ 34641.108SkamilATF_TC_BODY(name, tc) \ 34651.108Skamil{ \ 34661.108Skamil \ 34671.108Skamil traceme_vfork_fork_body(fun); \ 34681.108Skamil} 34691.108Skamil 34701.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork) 34711.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork) 34721.110Skamil#endif 34731.108Skamil 34741.108Skamil/// ---------------------------------------------------------------------------- 34751.108Skamil 34761.54Skamilenum bytes_transfer_type { 34771.54Skamil BYTES_TRANSFER_DATA, 34781.54Skamil BYTES_TRANSFER_DATAIO, 34791.54Skamil BYTES_TRANSFER_TEXT, 34801.54Skamil BYTES_TRANSFER_TEXTIO, 34811.54Skamil BYTES_TRANSFER_AUXV 34821.54Skamil}; 34831.31Skamil 34841.54Skamilstatic int __used 34851.54Skamilbytes_transfer_dummy(int a, int b, int c, int d) 34861.54Skamil{ 34871.54Skamil int e, f, g, h; 34881.1Skamil 34891.54Skamil a *= 4; 34901.54Skamil b += 3; 34911.54Skamil c -= 2; 34921.54Skamil d /= 1; 34931.1Skamil 34941.54Skamil e = strtol("10", NULL, 10); 34951.54Skamil f = strtol("20", NULL, 10); 34961.54Skamil g = strtol("30", NULL, 10); 34971.54Skamil h = strtol("40", NULL, 10); 34981.1Skamil 34991.54Skamil return (a + b * c - d) + (e * f - g / h); 35001.1Skamil} 35011.1Skamil 35021.54Skamilstatic void 35031.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type) 35041.1Skamil{ 35051.1Skamil const int exitval = 5; 35061.1Skamil const int sigval = SIGSTOP; 35071.1Skamil pid_t child, wpid; 35081.54Skamil bool skip = false; 35091.1Skamil 35101.54Skamil int lookup_me = 0; 35111.54Skamil uint8_t lookup_me8 = 0; 35121.54Skamil uint16_t lookup_me16 = 0; 35131.54Skamil uint32_t lookup_me32 = 0; 35141.54Skamil uint64_t lookup_me64 = 0; 35151.1Skamil 35161.54Skamil int magic = 0x13579246; 35171.54Skamil uint8_t magic8 = 0xab; 35181.54Skamil uint16_t magic16 = 0x1234; 35191.54Skamil uint32_t magic32 = 0x98765432; 35201.54Skamil uint64_t magic64 = 0xabcdef0123456789; 35211.1Skamil 35221.54Skamil struct ptrace_io_desc io; 35231.1Skamil#if defined(TWAIT_HAVE_STATUS) 35241.1Skamil int status; 35251.1Skamil#endif 35261.60Skre /* 513 is just enough, for the purposes of ATF it's good enough */ 35271.60Skre AuxInfo ai[513], *aip; 35281.55Schristos 35291.55Schristos ATF_REQUIRE(size < sizeof(ai)); 35301.1Skamil 35311.54Skamil /* Prepare variables for .TEXT transfers */ 35321.54Skamil switch (type) { 35331.54Skamil case BYTES_TRANSFER_TEXT: 35341.54Skamil memcpy(&magic, bytes_transfer_dummy, sizeof(magic)); 35351.54Skamil break; 35361.54Skamil case BYTES_TRANSFER_TEXTIO: 35371.54Skamil switch (size) { 35381.54Skamil case 8: 35391.54Skamil memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8)); 35401.54Skamil break; 35411.54Skamil case 16: 35421.54Skamil memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16)); 35431.54Skamil break; 35441.54Skamil case 32: 35451.54Skamil memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32)); 35461.54Skamil break; 35471.54Skamil case 64: 35481.54Skamil memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64)); 35491.54Skamil break; 35501.54Skamil } 35511.54Skamil break; 35521.54Skamil default: 35531.54Skamil break; 35541.54Skamil } 35551.1Skamil 35561.54Skamil /* Prepare variables for PIOD and AUXV transfers */ 35571.54Skamil switch (type) { 35581.54Skamil case BYTES_TRANSFER_TEXTIO: 35591.54Skamil case BYTES_TRANSFER_DATAIO: 35601.54Skamil io.piod_op = operation; 35611.54Skamil switch (size) { 35621.54Skamil case 8: 35631.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 35641.54Skamil (void *)bytes_transfer_dummy : 35651.54Skamil &lookup_me8; 35661.54Skamil io.piod_addr = &lookup_me8; 35671.54Skamil io.piod_len = sizeof(lookup_me8); 35681.54Skamil break; 35691.54Skamil case 16: 35701.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 35711.54Skamil (void *)bytes_transfer_dummy : 35721.54Skamil &lookup_me16; 35731.54Skamil io.piod_addr = &lookup_me16; 35741.54Skamil io.piod_len = sizeof(lookup_me16); 35751.54Skamil break; 35761.54Skamil case 32: 35771.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 35781.54Skamil (void *)bytes_transfer_dummy : 35791.54Skamil &lookup_me32; 35801.54Skamil io.piod_addr = &lookup_me32; 35811.54Skamil io.piod_len = sizeof(lookup_me32); 35821.54Skamil break; 35831.54Skamil case 64: 35841.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 35851.54Skamil (void *)bytes_transfer_dummy : 35861.54Skamil &lookup_me64; 35871.54Skamil io.piod_addr = &lookup_me64; 35881.54Skamil io.piod_len = sizeof(lookup_me64); 35891.54Skamil break; 35901.54Skamil default: 35911.54Skamil break; 35921.54Skamil } 35931.54Skamil break; 35941.54Skamil case BYTES_TRANSFER_AUXV: 35951.54Skamil io.piod_op = operation; 35961.54Skamil io.piod_offs = 0; 35971.54Skamil io.piod_addr = ai; 35981.54Skamil io.piod_len = size; 35991.54Skamil break; 36001.54Skamil default: 36011.54Skamil break; 36021.1Skamil } 36031.1Skamil 36041.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 36051.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 36061.1Skamil if (child == 0) { 36071.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 36081.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 36091.1Skamil 36101.54Skamil switch (type) { 36111.54Skamil case BYTES_TRANSFER_DATA: 36121.54Skamil switch (operation) { 36131.54Skamil case PT_READ_D: 36141.54Skamil case PT_READ_I: 36151.54Skamil lookup_me = magic; 36161.54Skamil break; 36171.54Skamil default: 36181.54Skamil break; 36191.54Skamil } 36201.54Skamil break; 36211.54Skamil case BYTES_TRANSFER_DATAIO: 36221.54Skamil switch (operation) { 36231.54Skamil case PIOD_READ_D: 36241.54Skamil case PIOD_READ_I: 36251.54Skamil switch (size) { 36261.54Skamil case 8: 36271.54Skamil lookup_me8 = magic8; 36281.54Skamil break; 36291.54Skamil case 16: 36301.54Skamil lookup_me16 = magic16; 36311.54Skamil break; 36321.54Skamil case 32: 36331.54Skamil lookup_me32 = magic32; 36341.54Skamil break; 36351.54Skamil case 64: 36361.54Skamil lookup_me64 = magic64; 36371.54Skamil break; 36381.54Skamil default: 36391.54Skamil break; 36401.54Skamil } 36411.54Skamil break; 36421.54Skamil default: 36431.54Skamil break; 36441.54Skamil } 36451.54Skamil default: 36461.54Skamil break; 36471.54Skamil } 36481.54Skamil 36491.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 36501.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 36511.1Skamil 36521.54Skamil /* Handle PIOD and PT separately as operation values overlap */ 36531.54Skamil switch (type) { 36541.54Skamil case BYTES_TRANSFER_DATA: 36551.54Skamil switch (operation) { 36561.54Skamil case PT_WRITE_D: 36571.54Skamil case PT_WRITE_I: 36581.54Skamil FORKEE_ASSERT_EQ(lookup_me, magic); 36591.54Skamil break; 36601.54Skamil default: 36611.54Skamil break; 36621.54Skamil } 36631.54Skamil break; 36641.54Skamil case BYTES_TRANSFER_DATAIO: 36651.54Skamil switch (operation) { 36661.54Skamil case PIOD_WRITE_D: 36671.54Skamil case PIOD_WRITE_I: 36681.54Skamil switch (size) { 36691.54Skamil case 8: 36701.54Skamil FORKEE_ASSERT_EQ(lookup_me8, magic8); 36711.54Skamil break; 36721.54Skamil case 16: 36731.54Skamil FORKEE_ASSERT_EQ(lookup_me16, magic16); 36741.54Skamil break; 36751.54Skamil case 32: 36761.54Skamil FORKEE_ASSERT_EQ(lookup_me32, magic32); 36771.54Skamil break; 36781.54Skamil case 64: 36791.54Skamil FORKEE_ASSERT_EQ(lookup_me64, magic64); 36801.54Skamil break; 36811.54Skamil default: 36821.54Skamil break; 36831.54Skamil } 36841.54Skamil break; 36851.54Skamil default: 36861.54Skamil break; 36871.54Skamil } 36881.54Skamil break; 36891.54Skamil case BYTES_TRANSFER_TEXT: 36901.54Skamil FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy, 36911.54Skamil sizeof(magic)) == 0); 36921.54Skamil break; 36931.54Skamil case BYTES_TRANSFER_TEXTIO: 36941.54Skamil switch (size) { 36951.54Skamil case 8: 36961.54Skamil FORKEE_ASSERT(memcmp(&magic8, 36971.54Skamil bytes_transfer_dummy, 36981.54Skamil sizeof(magic8)) == 0); 36991.54Skamil break; 37001.54Skamil case 16: 37011.54Skamil FORKEE_ASSERT(memcmp(&magic16, 37021.54Skamil bytes_transfer_dummy, 37031.54Skamil sizeof(magic16)) == 0); 37041.54Skamil break; 37051.54Skamil case 32: 37061.54Skamil FORKEE_ASSERT(memcmp(&magic32, 37071.54Skamil bytes_transfer_dummy, 37081.54Skamil sizeof(magic32)) == 0); 37091.54Skamil break; 37101.54Skamil case 64: 37111.54Skamil FORKEE_ASSERT(memcmp(&magic64, 37121.54Skamil bytes_transfer_dummy, 37131.54Skamil sizeof(magic64)) == 0); 37141.54Skamil break; 37151.54Skamil } 37161.54Skamil break; 37171.54Skamil default: 37181.54Skamil break; 37191.54Skamil } 37201.54Skamil 37211.13Schristos DPRINTF("Before exiting of the child process\n"); 37221.1Skamil _exit(exitval); 37231.1Skamil } 37241.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 37251.1Skamil 37261.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 37271.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 37281.1Skamil 37291.1Skamil validate_status_stopped(status, sigval); 37301.1Skamil 37311.54Skamil /* Check PaX MPROTECT */ 37321.54Skamil if (!can_we_write_to_text(child)) { 37331.54Skamil switch (type) { 37341.54Skamil case BYTES_TRANSFER_TEXTIO: 37351.54Skamil switch (operation) { 37361.54Skamil case PIOD_WRITE_D: 37371.54Skamil case PIOD_WRITE_I: 37381.54Skamil skip = true; 37391.54Skamil break; 37401.54Skamil default: 37411.54Skamil break; 37421.54Skamil } 37431.54Skamil break; 37441.54Skamil case BYTES_TRANSFER_TEXT: 37451.54Skamil switch (operation) { 37461.54Skamil case PT_WRITE_D: 37471.54Skamil case PT_WRITE_I: 37481.54Skamil skip = true; 37491.54Skamil break; 37501.54Skamil default: 37511.54Skamil break; 37521.54Skamil } 37531.54Skamil break; 37541.54Skamil default: 37551.54Skamil break; 37561.54Skamil } 37571.54Skamil } 37581.1Skamil 37591.54Skamil /* Bailout cleanly killing the child process */ 37601.54Skamil if (skip) { 37611.54Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1); 37621.54Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 37631.54Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 37641.54Skamil child); 37651.1Skamil 37661.54Skamil validate_status_signaled(status, SIGKILL, 0); 37671.1Skamil 37681.54Skamil atf_tc_skip("PaX MPROTECT setup prevents writes to .text"); 37691.54Skamil } 37701.1Skamil 37711.54Skamil DPRINTF("Calling operation to transfer bytes between child=%d and " 37721.54Skamil "parent=%d\n", child, getpid()); 37731.1Skamil 37741.54Skamil switch (type) { 37751.54Skamil case BYTES_TRANSFER_TEXTIO: 37761.54Skamil case BYTES_TRANSFER_DATAIO: 37771.54Skamil case BYTES_TRANSFER_AUXV: 37781.54Skamil switch (operation) { 37791.54Skamil case PIOD_WRITE_D: 37801.54Skamil case PIOD_WRITE_I: 37811.54Skamil switch (size) { 37821.54Skamil case 8: 37831.54Skamil lookup_me8 = magic8; 37841.54Skamil break; 37851.54Skamil case 16: 37861.54Skamil lookup_me16 = magic16; 37871.54Skamil break; 37881.54Skamil case 32: 37891.54Skamil lookup_me32 = magic32; 37901.54Skamil break; 37911.54Skamil case 64: 37921.54Skamil lookup_me64 = magic64; 37931.54Skamil break; 37941.54Skamil default: 37951.54Skamil break; 37961.54Skamil } 37971.54Skamil break; 37981.54Skamil default: 37991.54Skamil break; 38001.54Skamil } 38011.54Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); 38021.54Skamil switch (operation) { 38031.54Skamil case PIOD_READ_D: 38041.54Skamil case PIOD_READ_I: 38051.54Skamil switch (size) { 38061.54Skamil case 8: 38071.54Skamil ATF_REQUIRE_EQ(lookup_me8, magic8); 38081.54Skamil break; 38091.54Skamil case 16: 38101.54Skamil ATF_REQUIRE_EQ(lookup_me16, magic16); 38111.54Skamil break; 38121.54Skamil case 32: 38131.54Skamil ATF_REQUIRE_EQ(lookup_me32, magic32); 38141.54Skamil break; 38151.54Skamil case 64: 38161.54Skamil ATF_REQUIRE_EQ(lookup_me64, magic64); 38171.54Skamil break; 38181.54Skamil default: 38191.54Skamil break; 38201.54Skamil } 38211.54Skamil break; 38221.54Skamil case PIOD_READ_AUXV: 38231.54Skamil DPRINTF("Asserting that AUXV length (%zu) is > 0\n", 38241.54Skamil io.piod_len); 38251.54Skamil ATF_REQUIRE(io.piod_len > 0); 38261.54Skamil for (aip = ai; aip->a_type != AT_NULL; aip++) 38271.54Skamil DPRINTF("a_type=%#llx a_v=%#llx\n", 38281.54Skamil (long long int)aip->a_type, 38291.54Skamil (long long int)aip->a_v); 38301.54Skamil break; 38311.54Skamil default: 38321.54Skamil break; 38331.54Skamil } 38341.54Skamil break; 38351.54Skamil case BYTES_TRANSFER_TEXT: 38361.54Skamil switch (operation) { 38371.54Skamil case PT_READ_D: 38381.54Skamil case PT_READ_I: 38391.54Skamil errno = 0; 38401.54Skamil lookup_me = ptrace(operation, child, 38411.54Skamil bytes_transfer_dummy, 0); 38421.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 38431.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 38441.54Skamil break; 38451.54Skamil case PT_WRITE_D: 38461.54Skamil case PT_WRITE_I: 38471.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, 38481.54Skamil bytes_transfer_dummy, magic) 38491.54Skamil != -1); 38501.54Skamil break; 38511.54Skamil default: 38521.54Skamil break; 38531.54Skamil } 38541.54Skamil break; 38551.54Skamil case BYTES_TRANSFER_DATA: 38561.54Skamil switch (operation) { 38571.54Skamil case PT_READ_D: 38581.54Skamil case PT_READ_I: 38591.54Skamil errno = 0; 38601.54Skamil lookup_me = ptrace(operation, child, &lookup_me, 0); 38611.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 38621.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 38631.54Skamil break; 38641.54Skamil case PT_WRITE_D: 38651.54Skamil case PT_WRITE_I: 38661.54Skamil lookup_me = magic; 38671.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me, 38681.54Skamil magic) != -1); 38691.54Skamil break; 38701.54Skamil default: 38711.54Skamil break; 38721.54Skamil } 38731.54Skamil break; 38741.54Skamil default: 38751.54Skamil break; 38761.54Skamil } 38771.1Skamil 38781.13Schristos DPRINTF("Before resuming the child process where it left off and " 38791.1Skamil "without signal to be sent\n"); 38801.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 38811.1Skamil 38821.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38831.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 38841.1Skamil 38851.1Skamil validate_status_exited(status, exitval); 38861.1Skamil 38871.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38881.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 38891.1Skamil} 38901.1Skamil 38911.61Skre#define BYTES_TRANSFER(test, operation, size, type) \ 38921.61SkreATF_TC(test); \ 38931.61SkreATF_TC_HEAD(test, tc) \ 38941.61Skre{ \ 38951.61Skre atf_tc_set_md_var(tc, "descr", \ 38961.61Skre "Verify bytes transfer operation" #operation " and size " #size \ 38971.61Skre " of type " #type); \ 38981.61Skre} \ 38991.61Skre \ 39001.61SkreATF_TC_BODY(test, tc) \ 39011.61Skre{ \ 39021.61Skre \ 39031.61Skre bytes_transfer(operation, size, BYTES_TRANSFER_##type); \ 39041.1Skamil} 39051.1Skamil 39061.54Skamil// DATA 39071.1Skamil 39081.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO) 39091.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO) 39101.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO) 39111.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO) 39121.54Skamil 39131.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO) 39141.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO) 39151.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO) 39161.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO) 39171.54Skamil 39181.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO) 39191.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO) 39201.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO) 39211.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO) 39221.54Skamil 39231.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO) 39241.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO) 39251.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO) 39261.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO) 39271.54Skamil 39281.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA) 39291.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA) 39301.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA) 39311.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA) 39321.54Skamil 39331.54Skamil// TEXT 39341.54Skamil 39351.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO) 39361.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO) 39371.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO) 39381.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO) 39391.54Skamil 39401.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO) 39411.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO) 39421.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO) 39431.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO) 39441.54Skamil 39451.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO) 39461.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO) 39471.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO) 39481.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO) 39491.54Skamil 39501.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO) 39511.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO) 39521.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO) 39531.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO) 39541.54Skamil 39551.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT) 39561.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT) 39571.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT) 39581.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT) 39591.1Skamil 39601.54Skamil// AUXV 39611.1Skamil 39621.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV) 39631.1Skamil 39641.54Skamil/// ---------------------------------------------------------------------------- 39651.1Skamil 39661.101Skamilstatic void 39671.101Skamilbytes_transfer_alignment(const char *operation) 39681.101Skamil{ 39691.101Skamil const int exitval = 5; 39701.101Skamil const int sigval = SIGSTOP; 39711.101Skamil pid_t child, wpid; 39721.101Skamil#if defined(TWAIT_HAVE_STATUS) 39731.101Skamil int status; 39741.101Skamil#endif 39751.101Skamil char *buffer; 39761.101Skamil int vector; 39771.101Skamil size_t len; 39781.101Skamil size_t i; 39791.101Skamil int op; 39801.101Skamil 39811.101Skamil struct ptrace_io_desc io; 39821.101Skamil struct ptrace_siginfo info; 39831.101Skamil 39841.101Skamil memset(&io, 0, sizeof(io)); 39851.101Skamil memset(&info, 0, sizeof(info)); 39861.101Skamil 39871.101Skamil /* Testing misaligned byte transfer crossing page boundaries */ 39881.101Skamil len = sysconf(_SC_PAGESIZE) * 2; 39891.101Skamil buffer = malloc(len); 39901.101Skamil ATF_REQUIRE(buffer != NULL); 39911.101Skamil 39921.101Skamil /* Initialize the buffer with random data */ 39931.101Skamil for (i = 0; i < len; i++) 39941.101Skamil buffer[i] = i & 0xff; 39951.101Skamil 39961.101Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 39971.101Skamil SYSCALL_REQUIRE((child = fork()) != -1); 39981.101Skamil if (child == 0) { 39991.101Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 40001.101Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 40011.101Skamil 40021.101Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 40031.101Skamil FORKEE_ASSERT(raise(sigval) == 0); 40041.101Skamil 40051.101Skamil DPRINTF("Before exiting of the child process\n"); 40061.101Skamil _exit(exitval); 40071.101Skamil } 40081.101Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 40091.101Skamil 40101.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 40111.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 40121.101Skamil 40131.101Skamil validate_status_stopped(status, sigval); 40141.101Skamil 40151.101Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 40161.101Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 40171.101Skamil != -1); 40181.101Skamil 40191.101Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 40201.101Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 40211.101Skamil "si_errno=%#x\n", 40221.101Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 40231.101Skamil info.psi_siginfo.si_errno); 40241.101Skamil 40251.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 40261.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 40271.101Skamil 40281.101Skamil if (strcmp(operation, "PT_READ_I") == 0 || 40291.101Skamil strcmp(operation, "PT_READ_D") == 0) { 40301.101Skamil if (strcmp(operation, "PT_READ_I")) 40311.101Skamil op = PT_READ_I; 40321.101Skamil else 40331.101Skamil op = PT_READ_D; 40341.101Skamil 40351.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 40361.101Skamil errno = 0; 40371.101Skamil vector = ptrace(op, child, buffer + i, 0); 40381.101Skamil ATF_REQUIRE_EQ(errno, 0); 40391.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 40401.101Skamil } 40411.101Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 40421.101Skamil strcmp(operation, "PT_WRITE_D") == 0) { 40431.101Skamil if (strcmp(operation, "PT_WRITE_I")) 40441.101Skamil op = PT_WRITE_I; 40451.101Skamil else 40461.101Skamil op = PT_WRITE_D; 40471.101Skamil 40481.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 40491.101Skamil memcpy(&vector, buffer + i, sizeof(int)); 40501.101Skamil SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector) 40511.101Skamil != -1); 40521.101Skamil } 40531.101Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 40541.101Skamil strcmp(operation, "PIOD_READ_D") == 0) { 40551.101Skamil if (strcmp(operation, "PIOD_READ_I")) 40561.101Skamil op = PIOD_READ_I; 40571.101Skamil else 40581.101Skamil op = PIOD_READ_D; 40591.101Skamil 40601.101Skamil io.piod_op = op; 40611.101Skamil io.piod_addr = &vector; 40621.101Skamil io.piod_len = sizeof(int); 40631.101Skamil 40641.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 40651.101Skamil io.piod_offs = buffer + i; 40661.101Skamil 40671.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 40681.101Skamil != -1); 40691.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 40701.101Skamil } 40711.101Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 40721.101Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 40731.101Skamil if (strcmp(operation, "PIOD_WRITE_I")) 40741.101Skamil op = PIOD_WRITE_I; 40751.101Skamil else 40761.101Skamil op = PIOD_WRITE_D; 40771.101Skamil 40781.101Skamil io.piod_op = op; 40791.101Skamil io.piod_addr = &vector; 40801.101Skamil io.piod_len = sizeof(int); 40811.101Skamil 40821.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 40831.101Skamil io.piod_offs = buffer + i; 40841.101Skamil 40851.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 40861.101Skamil != -1); 40871.101Skamil } 40881.101Skamil } else if (strcmp(operation, "PIOD_READ_AUXV") == 0) { 40891.101Skamil io.piod_op = PIOD_READ_AUXV; 40901.101Skamil io.piod_addr = &vector; 40911.101Skamil io.piod_len = sizeof(int); 40921.101Skamil 40931.101Skamil errno = 0; 40941.101Skamil i = 0; 40951.101Skamil /* Read the whole AUXV vector, it has no clear length */ 40961.120Skamil while (io.piod_len > 0) { 40971.101Skamil io.piod_offs = (void *)(intptr_t)i; 40981.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 40991.120Skamil != -1 || (io.piod_len == 0 && i > 0)); 41001.101Skamil ++i; 41011.101Skamil } 41021.101Skamil } 41031.101Skamil 41041.101Skamil DPRINTF("Before resuming the child process where it left off " 41051.101Skamil "and without signal to be sent\n"); 41061.101Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 41071.101Skamil 41081.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41091.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 41101.101Skamil child); 41111.101Skamil 41121.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41131.101Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 41141.101Skamil} 41151.101Skamil 41161.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation) \ 41171.101SkamilATF_TC(test); \ 41181.101SkamilATF_TC_HEAD(test, tc) \ 41191.101Skamil{ \ 41201.101Skamil atf_tc_set_md_var(tc, "descr", \ 41211.101Skamil "Verify bytes transfer for potentially misaligned " \ 41221.101Skamil "operation " operation); \ 41231.101Skamil} \ 41241.101Skamil \ 41251.101SkamilATF_TC_BODY(test, tc) \ 41261.101Skamil{ \ 41271.101Skamil \ 41281.101Skamil bytes_transfer_alignment(operation); \ 41291.101Skamil} 41301.101Skamil 41311.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I") 41321.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D") 41331.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I") 41341.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D") 41351.101Skamil 41361.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I") 41371.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D") 41381.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I") 41391.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D") 41401.101Skamil 41411.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV") 41421.101Skamil 41431.101Skamil/// ---------------------------------------------------------------------------- 41441.101Skamil 41451.115Skamilstatic void 41461.115Skamilbytes_transfer_eof(const char *operation) 41471.115Skamil{ 41481.115Skamil const int exitval = 5; 41491.115Skamil const int sigval = SIGSTOP; 41501.115Skamil pid_t child, wpid; 41511.115Skamil#if defined(TWAIT_HAVE_STATUS) 41521.115Skamil int status; 41531.115Skamil#endif 41541.115Skamil FILE *fp; 41551.115Skamil char *p; 41561.115Skamil int vector; 41571.115Skamil int op; 41581.115Skamil 41591.115Skamil struct ptrace_io_desc io; 41601.115Skamil struct ptrace_siginfo info; 41611.115Skamil 41621.115Skamil memset(&io, 0, sizeof(io)); 41631.115Skamil memset(&info, 0, sizeof(info)); 41641.115Skamil 41651.115Skamil vector = 0; 41661.115Skamil 41671.115Skamil fp = tmpfile(); 41681.115Skamil ATF_REQUIRE(fp != NULL); 41691.115Skamil 41701.115Skamil p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0); 41711.115Skamil ATF_REQUIRE(p != MAP_FAILED); 41721.115Skamil 41731.115Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 41741.115Skamil SYSCALL_REQUIRE((child = fork()) != -1); 41751.115Skamil if (child == 0) { 41761.115Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 41771.115Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 41781.115Skamil 41791.115Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 41801.115Skamil FORKEE_ASSERT(raise(sigval) == 0); 41811.115Skamil 41821.115Skamil DPRINTF("Before exiting of the child process\n"); 41831.115Skamil _exit(exitval); 41841.115Skamil } 41851.115Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 41861.115Skamil 41871.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41881.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 41891.115Skamil 41901.115Skamil validate_status_stopped(status, sigval); 41911.115Skamil 41921.115Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 41931.115Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 41941.115Skamil != -1); 41951.115Skamil 41961.115Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 41971.115Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 41981.115Skamil "si_errno=%#x\n", 41991.115Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 42001.115Skamil info.psi_siginfo.si_errno); 42011.115Skamil 42021.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 42031.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 42041.115Skamil 42051.115Skamil if (strcmp(operation, "PT_READ_I") == 0 || 42061.115Skamil strcmp(operation, "PT_READ_D") == 0) { 42071.115Skamil if (strcmp(operation, "PT_READ_I")) 42081.115Skamil op = PT_READ_I; 42091.115Skamil else 42101.115Skamil op = PT_READ_D; 42111.115Skamil 42121.115Skamil errno = 0; 42131.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, 0) == -1); 42141.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 42151.115Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 42161.115Skamil strcmp(operation, "PT_WRITE_D") == 0) { 42171.115Skamil if (strcmp(operation, "PT_WRITE_I")) 42181.115Skamil op = PT_WRITE_I; 42191.115Skamil else 42201.115Skamil op = PT_WRITE_D; 42211.115Skamil 42221.115Skamil errno = 0; 42231.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, vector) == -1); 42241.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 42251.115Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 42261.115Skamil strcmp(operation, "PIOD_READ_D") == 0) { 42271.115Skamil if (strcmp(operation, "PIOD_READ_I")) 42281.115Skamil op = PIOD_READ_I; 42291.115Skamil else 42301.115Skamil op = PIOD_READ_D; 42311.115Skamil 42321.115Skamil io.piod_op = op; 42331.115Skamil io.piod_addr = &vector; 42341.115Skamil io.piod_len = sizeof(int); 42351.115Skamil io.piod_offs = p; 42361.115Skamil 42371.115Skamil errno = 0; 42381.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 42391.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 42401.115Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 42411.115Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 42421.115Skamil if (strcmp(operation, "PIOD_WRITE_I")) 42431.115Skamil op = PIOD_WRITE_I; 42441.115Skamil else 42451.115Skamil op = PIOD_WRITE_D; 42461.115Skamil 42471.115Skamil io.piod_op = op; 42481.115Skamil io.piod_addr = &vector; 42491.115Skamil io.piod_len = sizeof(int); 42501.115Skamil io.piod_offs = p; 42511.115Skamil 42521.115Skamil errno = 0; 42531.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 42541.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 42551.115Skamil } 42561.115Skamil 42571.115Skamil DPRINTF("Before resuming the child process where it left off " 42581.115Skamil "and without signal to be sent\n"); 42591.115Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 42601.115Skamil 42611.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 42621.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 42631.115Skamil child); 42641.115Skamil 42651.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 42661.115Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 42671.115Skamil} 42681.115Skamil 42691.115Skamil#define BYTES_TRANSFER_EOF(test, operation) \ 42701.115SkamilATF_TC(test); \ 42711.115SkamilATF_TC_HEAD(test, tc) \ 42721.115Skamil{ \ 42731.115Skamil atf_tc_set_md_var(tc, "descr", \ 42741.115Skamil "Verify bytes EOF byte transfer for the " operation \ 42751.115Skamil " operation"); \ 42761.115Skamil} \ 42771.115Skamil \ 42781.115SkamilATF_TC_BODY(test, tc) \ 42791.115Skamil{ \ 42801.115Skamil \ 42811.115Skamil bytes_transfer_eof(operation); \ 42821.115Skamil} 42831.115Skamil 42841.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_i, "PT_READ_I") 42851.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_d, "PT_READ_D") 42861.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_i, "PT_WRITE_I") 42871.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_d, "PT_WRITE_D") 42881.115Skamil 42891.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_i, "PIOD_READ_I") 42901.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_d, "PIOD_READ_D") 42911.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_i, "PIOD_WRITE_I") 42921.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_d, "PIOD_WRITE_D") 42931.115Skamil 42941.115Skamil/// ---------------------------------------------------------------------------- 42951.115Skamil 42961.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS) 42971.72Skamilstatic void 42981.72Skamilaccess_regs(const char *regset, const char *aux) 42991.1Skamil{ 43001.1Skamil const int exitval = 5; 43011.1Skamil const int sigval = SIGSTOP; 43021.1Skamil pid_t child, wpid; 43031.1Skamil#if defined(TWAIT_HAVE_STATUS) 43041.1Skamil int status; 43051.1Skamil#endif 43061.72Skamil#if defined(HAVE_GPREGS) 43071.72Skamil struct reg gpr; 43081.76Sscole register_t rgstr; 43091.1Skamil#endif 43101.72Skamil#if defined(HAVE_FPREGS) 43111.72Skamil struct fpreg fpr; 43121.1Skamil#endif 43131.76Sscole 43141.72Skamil#if !defined(HAVE_GPREGS) 43151.72Skamil if (strcmp(regset, "regs") == 0) 43161.72Skamil atf_tc_fail("Impossible test scenario!"); 43171.1Skamil#endif 43181.1Skamil 43191.72Skamil#if !defined(HAVE_FPREGS) 43201.72Skamil if (strcmp(regset, "fpregs") == 0) 43211.72Skamil atf_tc_fail("Impossible test scenario!"); 43221.1Skamil#endif 43231.1Skamil 43241.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 43251.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 43261.1Skamil if (child == 0) { 43271.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 43281.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 43291.1Skamil 43301.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 43311.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 43321.1Skamil 43331.13Schristos DPRINTF("Before exiting of the child process\n"); 43341.1Skamil _exit(exitval); 43351.1Skamil } 43361.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 43371.1Skamil 43381.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43391.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 43401.1Skamil 43411.1Skamil validate_status_stopped(status, sigval); 43421.1Skamil 43431.1Skamil#if defined(HAVE_GPREGS) 43441.72Skamil if (strcmp(regset, "regs") == 0) { 43451.72Skamil DPRINTF("Call GETREGS for the child process\n"); 43461.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1); 43471.72Skamil 43481.72Skamil if (strcmp(aux, "none") == 0) { 43491.72Skamil DPRINTF("Retrieved registers\n"); 43501.72Skamil } else if (strcmp(aux, "pc") == 0) { 43511.72Skamil rgstr = PTRACE_REG_PC(&gpr); 43521.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 43531.72Skamil } else if (strcmp(aux, "set_pc") == 0) { 43541.72Skamil rgstr = PTRACE_REG_PC(&gpr); 43551.72Skamil PTRACE_REG_SET_PC(&gpr, rgstr); 43561.72Skamil } else if (strcmp(aux, "sp") == 0) { 43571.72Skamil rgstr = PTRACE_REG_SP(&gpr); 43581.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 43591.72Skamil } else if (strcmp(aux, "intrv") == 0) { 43601.72Skamil rgstr = PTRACE_REG_INTRV(&gpr); 43611.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 43621.72Skamil } else if (strcmp(aux, "setregs") == 0) { 43631.72Skamil DPRINTF("Call SETREGS for the child process\n"); 43641.72Skamil SYSCALL_REQUIRE( 43651.72Skamil ptrace(PT_GETREGS, child, &gpr, 0) != -1); 43661.72Skamil } 43671.72Skamil } 43681.1Skamil#endif 43691.1Skamil 43701.72Skamil#if defined(HAVE_FPREGS) 43711.72Skamil if (strcmp(regset, "fpregs") == 0) { 43721.72Skamil DPRINTF("Call GETFPREGS for the child process\n"); 43731.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1); 43741.72Skamil 43751.72Skamil if (strcmp(aux, "getfpregs") == 0) { 43761.72Skamil DPRINTF("Retrieved FP registers\n"); 43771.72Skamil } else if (strcmp(aux, "setfpregs") == 0) { 43781.72Skamil DPRINTF("Call SETFPREGS for the child\n"); 43791.72Skamil SYSCALL_REQUIRE( 43801.72Skamil ptrace(PT_SETFPREGS, child, &fpr, 0) != -1); 43811.72Skamil } 43821.1Skamil } 43831.1Skamil#endif 43841.1Skamil 43851.13Schristos DPRINTF("Before resuming the child process where it left off and " 43861.1Skamil "without signal to be sent\n"); 43871.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 43881.1Skamil 43891.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43901.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 43911.1Skamil 43921.1Skamil validate_status_exited(status, exitval); 43931.1Skamil 43941.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43951.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 43961.1Skamil} 43971.1Skamil 43981.72Skamil#define ACCESS_REGS(test, regset, aux) \ 43991.72SkamilATF_TC(test); \ 44001.72SkamilATF_TC_HEAD(test, tc) \ 44011.72Skamil{ \ 44021.72Skamil atf_tc_set_md_var(tc, "descr", \ 44031.72Skamil "Verify " regset " with auxiliary operation: " aux); \ 44041.72Skamil} \ 44051.72Skamil \ 44061.72SkamilATF_TC_BODY(test, tc) \ 44071.72Skamil{ \ 44081.72Skamil \ 44091.72Skamil access_regs(regset, aux); \ 44101.1Skamil} 44111.1Skamil#endif 44121.1Skamil 44131.72Skamil#if defined(HAVE_GPREGS) 44141.72SkamilACCESS_REGS(access_regs1, "regs", "none") 44151.72SkamilACCESS_REGS(access_regs2, "regs", "pc") 44161.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc") 44171.72SkamilACCESS_REGS(access_regs4, "regs", "sp") 44181.72SkamilACCESS_REGS(access_regs5, "regs", "intrv") 44191.72SkamilACCESS_REGS(access_regs6, "regs", "setregs") 44201.1Skamil#endif 44211.1Skamil#if defined(HAVE_FPREGS) 44221.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs") 44231.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs") 44241.1Skamil#endif 44251.1Skamil 44261.72Skamil/// ---------------------------------------------------------------------------- 44271.1Skamil 44281.1Skamil#if defined(PT_STEP) 44291.1Skamilstatic void 44301.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored) 44311.1Skamil{ 44321.1Skamil const int exitval = 5; 44331.1Skamil const int sigval = SIGSTOP; 44341.1Skamil pid_t child, wpid; 44351.1Skamil#if defined(TWAIT_HAVE_STATUS) 44361.1Skamil int status; 44371.1Skamil#endif 44381.1Skamil int happy; 44391.95Skamil struct sigaction sa; 44401.81Skamil struct ptrace_siginfo info; 44411.95Skamil sigset_t intmask; 44421.95Skamil struct kinfo_proc2 kp; 44431.95Skamil size_t len = sizeof(kp); 44441.95Skamil 44451.95Skamil int name[6]; 44461.95Skamil const size_t namelen = __arraycount(name); 44471.95Skamil ki_sigset_t kp_sigmask; 44481.95Skamil ki_sigset_t kp_sigignore; 44491.1Skamil 44501.1Skamil#if defined(__arm__) 44511.1Skamil /* PT_STEP not supported on arm 32-bit */ 44521.1Skamil atf_tc_expect_fail("PR kern/52119"); 44531.1Skamil#endif 44541.1Skamil 44551.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 44561.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 44571.1Skamil if (child == 0) { 44581.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 44591.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 44601.1Skamil 44611.95Skamil if (masked) { 44621.95Skamil sigemptyset(&intmask); 44631.95Skamil sigaddset(&intmask, SIGTRAP); 44641.95Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 44651.95Skamil } 44661.95Skamil 44671.95Skamil if (ignored) { 44681.95Skamil memset(&sa, 0, sizeof(sa)); 44691.95Skamil sa.sa_handler = SIG_IGN; 44701.95Skamil sigemptyset(&sa.sa_mask); 44711.95Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 44721.95Skamil } 44731.95Skamil 44741.1Skamil happy = check_happy(999); 44751.1Skamil 44761.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 44771.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 44781.1Skamil 44791.1Skamil FORKEE_ASSERT_EQ(happy, check_happy(999)); 44801.1Skamil 44811.13Schristos DPRINTF("Before exiting of the child process\n"); 44821.1Skamil _exit(exitval); 44831.1Skamil } 44841.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 44851.1Skamil 44861.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44871.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44881.1Skamil 44891.1Skamil validate_status_stopped(status, sigval); 44901.1Skamil 44911.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 44921.81Skamil SYSCALL_REQUIRE( 44931.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 44941.81Skamil 44951.81Skamil DPRINTF("Before checking siginfo_t\n"); 44961.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 44971.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 44981.81Skamil 44991.95Skamil name[0] = CTL_KERN, 45001.95Skamil name[1] = KERN_PROC2, 45011.95Skamil name[2] = KERN_PROC_PID; 45021.95Skamil name[3] = child; 45031.95Skamil name[4] = sizeof(kp); 45041.95Skamil name[5] = 1; 45051.95Skamil 45061.95Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 45071.95Skamil 45081.95Skamil if (masked) 45091.95Skamil kp_sigmask = kp.p_sigmask; 45101.95Skamil 45111.95Skamil if (ignored) 45121.95Skamil kp_sigignore = kp.p_sigignore; 45131.95Skamil 45141.1Skamil while (N --> 0) { 45151.2Skamil if (setstep) { 45161.13Schristos DPRINTF("Before resuming the child process where it " 45171.2Skamil "left off and without signal to be sent (use " 45181.9Skamil "PT_SETSTEP and PT_CONTINUE)\n"); 45191.13Schristos SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1); 45201.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) 45211.2Skamil != -1); 45221.2Skamil } else { 45231.13Schristos DPRINTF("Before resuming the child process where it " 45241.2Skamil "left off and without signal to be sent (use " 45251.2Skamil "PT_STEP)\n"); 45261.13Schristos SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) 45271.2Skamil != -1); 45281.2Skamil } 45291.1Skamil 45301.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45311.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 45321.1Skamil child); 45331.1Skamil 45341.1Skamil validate_status_stopped(status, SIGTRAP); 45351.2Skamil 45361.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 45371.81Skamil SYSCALL_REQUIRE( 45381.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 45391.81Skamil 45401.81Skamil DPRINTF("Before checking siginfo_t\n"); 45411.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 45421.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE); 45431.81Skamil 45441.2Skamil if (setstep) { 45451.13Schristos SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1); 45461.2Skamil } 45471.95Skamil 45481.95Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 45491.95Skamil 45501.95Skamil if (masked) { 45511.95Skamil DPRINTF("kp_sigmask=" 45521.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 45531.95Skamil PRIx32 "\n", 45541.95Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 45551.95Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 45561.95Skamil 45571.95Skamil DPRINTF("kp.p_sigmask=" 45581.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 45591.95Skamil PRIx32 "\n", 45601.95Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 45611.95Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 45621.95Skamil 45631.95Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 45641.95Skamil sizeof(kp_sigmask))); 45651.95Skamil } 45661.95Skamil 45671.95Skamil if (ignored) { 45681.95Skamil DPRINTF("kp_sigignore=" 45691.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 45701.95Skamil PRIx32 "\n", 45711.95Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 45721.95Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 45731.95Skamil 45741.95Skamil DPRINTF("kp.p_sigignore=" 45751.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 45761.95Skamil PRIx32 "\n", 45771.95Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 45781.95Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 45791.95Skamil 45801.95Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 45811.95Skamil sizeof(kp_sigignore))); 45821.95Skamil } 45831.1Skamil } 45841.1Skamil 45851.13Schristos DPRINTF("Before resuming the child process where it left off and " 45861.1Skamil "without signal to be sent\n"); 45871.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 45881.1Skamil 45891.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45901.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 45911.1Skamil 45921.1Skamil validate_status_exited(status, exitval); 45931.1Skamil 45941.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45951.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 45961.1Skamil} 45971.1Skamil 45981.73Skamil#define PTRACE_STEP(test, N, setstep) \ 45991.73SkamilATF_TC(test); \ 46001.73SkamilATF_TC_HEAD(test, tc) \ 46011.73Skamil{ \ 46021.73Skamil atf_tc_set_md_var(tc, "descr", \ 46031.74Skamil "Verify " #N " (PT_SETSTEP set to: " #setstep ")"); \ 46041.73Skamil} \ 46051.73Skamil \ 46061.73SkamilATF_TC_BODY(test, tc) \ 46071.73Skamil{ \ 46081.73Skamil \ 46091.95Skamil ptrace_step(N, setstep, false, false); \ 46101.1Skamil} 46111.1Skamil 46121.73SkamilPTRACE_STEP(step1, 1, 0) 46131.73SkamilPTRACE_STEP(step2, 2, 0) 46141.73SkamilPTRACE_STEP(step3, 3, 0) 46151.73SkamilPTRACE_STEP(step4, 4, 0) 46161.73SkamilPTRACE_STEP(setstep1, 1, 1) 46171.73SkamilPTRACE_STEP(setstep2, 2, 1) 46181.73SkamilPTRACE_STEP(setstep3, 3, 1) 46191.73SkamilPTRACE_STEP(setstep4, 4, 1) 46201.95Skamil 46211.95SkamilATF_TC(step_signalmasked); 46221.95SkamilATF_TC_HEAD(step_signalmasked, tc) 46231.95Skamil{ 46241.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP"); 46251.95Skamil} 46261.95Skamil 46271.95SkamilATF_TC_BODY(step_signalmasked, tc) 46281.95Skamil{ 46291.95Skamil 46301.95Skamil ptrace_step(1, 0, true, false); 46311.95Skamil} 46321.95Skamil 46331.95SkamilATF_TC(step_signalignored); 46341.95SkamilATF_TC_HEAD(step_signalignored, tc) 46351.95Skamil{ 46361.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP"); 46371.95Skamil} 46381.95Skamil 46391.95SkamilATF_TC_BODY(step_signalignored, tc) 46401.95Skamil{ 46411.95Skamil 46421.95Skamil ptrace_step(1, 0, false, true); 46431.95Skamil} 46441.1Skamil#endif 46451.1Skamil 46461.73Skamil/// ---------------------------------------------------------------------------- 46471.1Skamil 46481.75Skamilstatic void 46491.75Skamilptrace_kill(const char *type) 46501.1Skamil{ 46511.75Skamil const int sigval = SIGSTOP; 46521.1Skamil pid_t child, wpid; 46531.1Skamil#if defined(TWAIT_HAVE_STATUS) 46541.1Skamil int status; 46551.1Skamil#endif 46561.1Skamil 46571.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 46581.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 46591.1Skamil if (child == 0) { 46601.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 46611.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 46621.1Skamil 46631.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 46641.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 46651.1Skamil 46661.1Skamil /* NOTREACHED */ 46671.1Skamil FORKEE_ASSERTX(0 && 46681.1Skamil "Child should be terminated by a signal from its parent"); 46691.1Skamil } 46701.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 46711.1Skamil 46721.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46731.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 46741.1Skamil 46751.1Skamil validate_status_stopped(status, sigval); 46761.1Skamil 46771.75Skamil DPRINTF("Before killing the child process with %s\n", type); 46781.75Skamil if (strcmp(type, "ptrace(PT_KILL)") == 0) { 46791.75Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1); 46801.75Skamil } else if (strcmp(type, "kill(SIGKILL)") == 0) { 46811.75Skamil kill(child, SIGKILL); 46821.75Skamil } else if (strcmp(type, "killpg(SIGKILL)") == 0) { 46831.75Skamil setpgid(child, 0); 46841.75Skamil killpg(getpgid(child), SIGKILL); 46851.75Skamil } 46861.1Skamil 46871.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46881.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 46891.1Skamil 46901.75Skamil validate_status_signaled(status, SIGKILL, 0); 46911.1Skamil 46921.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46931.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 46941.1Skamil} 46951.1Skamil 46961.75Skamil#define PTRACE_KILL(test, type) \ 46971.75SkamilATF_TC(test); \ 46981.75SkamilATF_TC_HEAD(test, tc) \ 46991.75Skamil{ \ 47001.75Skamil atf_tc_set_md_var(tc, "descr", \ 47011.75Skamil "Verify killing the child with " type); \ 47021.75Skamil} \ 47031.75Skamil \ 47041.75SkamilATF_TC_BODY(test, tc) \ 47051.75Skamil{ \ 47061.75Skamil \ 47071.75Skamil ptrace_kill(type); \ 47081.1Skamil} 47091.1Skamil 47101.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1 47111.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)") 47121.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)") 47131.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)") 47141.1Skamil 47151.75Skamil/// ---------------------------------------------------------------------------- 47161.1Skamil 47171.77Skamilstatic void 47181.77Skamiltraceme_lwpinfo(const int threads) 47191.1Skamil{ 47201.1Skamil const int sigval = SIGSTOP; 47211.77Skamil const int sigval2 = SIGINT; 47221.1Skamil pid_t child, wpid; 47231.1Skamil#if defined(TWAIT_HAVE_STATUS) 47241.1Skamil int status; 47251.1Skamil#endif 47261.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 47271.77Skamil struct ptrace_siginfo info; 47281.77Skamil 47291.77Skamil /* Maximum number of supported threads in this test */ 47301.77Skamil pthread_t t[3]; 47311.77Skamil int n, rv; 47321.77Skamil 47331.77Skamil ATF_REQUIRE((int)__arraycount(t) >= threads); 47341.1Skamil 47351.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 47361.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 47371.1Skamil if (child == 0) { 47381.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 47391.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 47401.1Skamil 47411.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 47421.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 47431.1Skamil 47441.77Skamil for (n = 0; n < threads; n++) { 47451.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 47461.77Skamil FORKEE_ASSERT(rv == 0); 47471.77Skamil } 47481.77Skamil 47491.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval2)); 47501.77Skamil FORKEE_ASSERT(raise(sigval2) == 0); 47511.77Skamil 47521.77Skamil /* NOTREACHED */ 47531.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 47541.1Skamil } 47551.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 47561.1Skamil 47571.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47581.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47591.1Skamil 47601.1Skamil validate_status_stopped(status, sigval); 47611.1Skamil 47621.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 47631.77Skamil SYSCALL_REQUIRE( 47641.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 47651.77Skamil 47661.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 47671.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 47681.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 47691.77Skamil info.psi_siginfo.si_errno); 47701.77Skamil 47711.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 47721.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 47731.77Skamil 47741.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 47751.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 47761.1Skamil 47771.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 47781.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 47791.1Skamil 47801.13Schristos DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n", 47811.77Skamil lwp.pl_lwpid); 47821.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 47831.1Skamil 47841.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 47851.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 47861.1Skamil 47871.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 47881.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 47891.1Skamil 47901.13Schristos DPRINTF("Before resuming the child process where it left off and " 47911.1Skamil "without signal to be sent\n"); 47921.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 47931.1Skamil 47941.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47951.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47961.1Skamil 47971.77Skamil validate_status_stopped(status, sigval2); 47981.77Skamil 47991.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 48001.77Skamil SYSCALL_REQUIRE( 48011.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 48021.77Skamil 48031.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 48041.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 48051.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 48061.77Skamil info.psi_siginfo.si_errno); 48071.77Skamil 48081.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2); 48091.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 48101.77Skamil 48111.77Skamil memset(&lwp, 0, sizeof(lwp)); 48121.77Skamil 48131.77Skamil for (n = 0; n <= threads; n++) { 48141.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48151.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48161.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 48171.77Skamil 48181.77Skamil DPRINTF("Assert that the thread exists\n"); 48191.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 48201.77Skamil 48211.77Skamil DPRINTF("Assert that lwp thread %d received expected event\n", 48221.77Skamil lwp.pl_lwpid); 48231.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ? 48241.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 48251.77Skamil } 48261.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48271.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48281.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 48291.77Skamil 48301.77Skamil DPRINTF("Assert that there are no more threads\n"); 48311.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 48321.77Skamil 48331.77Skamil DPRINTF("Before resuming the child process where it left off and " 48341.77Skamil "without signal to be sent\n"); 48351.77Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1); 48361.77Skamil 48371.77Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48381.77Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48391.77Skamil 48401.77Skamil validate_status_signaled(status, SIGKILL, 0); 48411.1Skamil 48421.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48431.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 48441.1Skamil} 48451.1Skamil 48461.77Skamil#define TRACEME_LWPINFO(test, threads) \ 48471.77SkamilATF_TC(test); \ 48481.77SkamilATF_TC_HEAD(test, tc) \ 48491.77Skamil{ \ 48501.77Skamil atf_tc_set_md_var(tc, "descr", \ 48511.77Skamil "Verify LWPINFO with the child with " #threads \ 48521.77Skamil " spawned extra threads"); \ 48531.77Skamil} \ 48541.77Skamil \ 48551.77SkamilATF_TC_BODY(test, tc) \ 48561.77Skamil{ \ 48571.77Skamil \ 48581.77Skamil traceme_lwpinfo(threads); \ 48591.1Skamil} 48601.1Skamil 48611.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0) 48621.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1) 48631.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2) 48641.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3) 48651.77Skamil 48661.77Skamil/// ---------------------------------------------------------------------------- 48671.77Skamil 48681.77Skamil#if defined(TWAIT_HAVE_PID) 48691.77Skamilstatic void 48701.77Skamilattach_lwpinfo(const int threads) 48711.1Skamil{ 48721.77Skamil const int sigval = SIGINT; 48731.1Skamil struct msg_fds parent_tracee, parent_tracer; 48741.1Skamil const int exitval_tracer = 10; 48751.1Skamil pid_t tracee, tracer, wpid; 48761.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 48771.1Skamil#if defined(TWAIT_HAVE_STATUS) 48781.1Skamil int status; 48791.1Skamil#endif 48801.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 48811.77Skamil struct ptrace_siginfo info; 48821.77Skamil 48831.77Skamil /* Maximum number of supported threads in this test */ 48841.77Skamil pthread_t t[3]; 48851.77Skamil int n, rv; 48861.1Skamil 48871.13Schristos DPRINTF("Spawn tracee\n"); 48881.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 48891.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 48901.1Skamil tracee = atf_utils_fork(); 48911.1Skamil if (tracee == 0) { 48921.1Skamil /* Wait for message from the parent */ 48931.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 48941.1Skamil 48951.77Skamil CHILD_FROM_PARENT("spawn threads", parent_tracee, msg); 48961.77Skamil 48971.77Skamil for (n = 0; n < threads; n++) { 48981.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 48991.77Skamil FORKEE_ASSERT(rv == 0); 49001.77Skamil } 49011.77Skamil 49021.77Skamil CHILD_TO_PARENT("tracee exit", parent_tracee, msg); 49031.77Skamil 49041.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 49051.77Skamil FORKEE_ASSERT(raise(sigval) == 0); 49061.77Skamil 49071.77Skamil /* NOTREACHED */ 49081.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 49091.1Skamil } 49101.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 49111.1Skamil 49121.13Schristos DPRINTF("Spawn debugger\n"); 49131.1Skamil tracer = atf_utils_fork(); 49141.1Skamil if (tracer == 0) { 49151.1Skamil /* No IPC to communicate with the child */ 49161.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 49171.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 49181.1Skamil 49191.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 49201.1Skamil FORKEE_REQUIRE_SUCCESS( 49211.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 49221.1Skamil 49231.1Skamil forkee_status_stopped(status, SIGSTOP); 49241.1Skamil 49251.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 49261.77Skamil "tracee"); 49271.77Skamil FORKEE_ASSERT( 49281.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 49291.77Skamil 49301.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 49311.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 49321.77Skamil "si_errno=%#x\n", 49331.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 49341.77Skamil info.psi_siginfo.si_errno); 49351.77Skamil 49361.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 49371.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 49381.77Skamil 49391.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 49401.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 49411.1Skamil != -1); 49421.1Skamil 49431.13Schristos DPRINTF("Assert that there exists a thread\n"); 49441.77Skamil FORKEE_ASSERTX(lwp.pl_lwpid > 0); 49451.1Skamil 49461.13Schristos DPRINTF("Assert that lwp thread %d received event " 49471.77Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 49481.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 49491.1Skamil 49501.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 49511.77Skamil "tracee\n"); 49521.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 49531.1Skamil != -1); 49541.1Skamil 49551.77Skamil DPRINTF("Assert that there are no more lwp threads in " 49561.77Skamil "tracee\n"); 49571.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 49581.1Skamil 49591.1Skamil /* Resume tracee with PT_CONTINUE */ 49601.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 49611.1Skamil 49621.1Skamil /* Inform parent that tracer has attached to tracee */ 49631.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 49641.77Skamil 49651.1Skamil /* Wait for parent */ 49661.1Skamil CHILD_FROM_PARENT("tracer wait", parent_tracer, msg); 49671.1Skamil 49681.77Skamil /* Wait for tracee and assert that it raised a signal */ 49691.77Skamil FORKEE_REQUIRE_SUCCESS( 49701.77Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 49711.77Skamil 49721.77Skamil forkee_status_stopped(status, SIGINT); 49731.77Skamil 49741.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 49751.77Skamil "child"); 49761.77Skamil FORKEE_ASSERT( 49771.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 49781.77Skamil 49791.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 49801.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 49811.77Skamil "si_errno=%#x\n", 49821.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 49831.77Skamil info.psi_siginfo.si_errno); 49841.77Skamil 49851.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 49861.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 49871.77Skamil 49881.77Skamil memset(&lwp, 0, sizeof(lwp)); 49891.77Skamil 49901.77Skamil for (n = 0; n <= threads; n++) { 49911.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 49921.77Skamil "child\n"); 49931.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, 49941.77Skamil sizeof(lwp)) != -1); 49951.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 49961.77Skamil 49971.77Skamil DPRINTF("Assert that the thread exists\n"); 49981.77Skamil FORKEE_ASSERT(lwp.pl_lwpid > 0); 49991.77Skamil 50001.77Skamil DPRINTF("Assert that lwp thread %d received expected " 50011.77Skamil "event\n", lwp.pl_lwpid); 50021.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 50031.77Skamil info.psi_lwpid == lwp.pl_lwpid ? 50041.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 50051.77Skamil } 50061.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 50071.77Skamil "tracee\n"); 50081.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 50091.77Skamil != -1); 50101.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 50111.77Skamil 50121.77Skamil DPRINTF("Assert that there are no more threads\n"); 50131.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 50141.77Skamil 50151.77Skamil DPRINTF("Before resuming the child process where it left off " 50161.77Skamil "and without signal to be sent\n"); 50171.77Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL) 50181.77Skamil != -1); 50191.77Skamil 50201.1Skamil /* Wait for tracee and assert that it exited */ 50211.1Skamil FORKEE_REQUIRE_SUCCESS( 50221.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 50231.1Skamil 50241.77Skamil forkee_status_signaled(status, SIGKILL, 0); 50251.1Skamil 50261.13Schristos DPRINTF("Before exiting of the tracer process\n"); 50271.1Skamil _exit(exitval_tracer); 50281.1Skamil } 50291.1Skamil 50301.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 50311.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 50321.1Skamil 50331.77Skamil DPRINTF("Resume the tracee and spawn threads\n"); 50341.77Skamil PARENT_TO_CHILD("spawn threads", parent_tracee, msg); 50351.77Skamil 50361.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 50371.77Skamil PARENT_FROM_CHILD("tracee exit", parent_tracee, msg); 50381.1Skamil 50391.77Skamil DPRINTF("Resume the tracer and let it detect multiple threads\n"); 50401.1Skamil PARENT_TO_CHILD("tracer wait", parent_tracer, msg); 50411.1Skamil 50421.13Schristos DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n", 50431.1Skamil TWAIT_FNAME); 50441.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 50451.1Skamil tracer); 50461.1Skamil 50471.1Skamil validate_status_exited(status, exitval_tracer); 50481.1Skamil 50491.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 50501.1Skamil TWAIT_FNAME); 50511.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 50521.1Skamil tracee); 50531.1Skamil 50541.77Skamil validate_status_signaled(status, SIGKILL, 0); 50551.1Skamil 50561.1Skamil msg_close(&parent_tracer); 50571.1Skamil msg_close(&parent_tracee); 50581.1Skamil} 50591.77Skamil 50601.77Skamil#define ATTACH_LWPINFO(test, threads) \ 50611.77SkamilATF_TC(test); \ 50621.77SkamilATF_TC_HEAD(test, tc) \ 50631.77Skamil{ \ 50641.77Skamil atf_tc_set_md_var(tc, "descr", \ 50651.77Skamil "Verify LWPINFO with the child with " #threads \ 50661.77Skamil " spawned extra threads (tracer is not the original " \ 50671.77Skamil "parent)"); \ 50681.77Skamil} \ 50691.77Skamil \ 50701.77SkamilATF_TC_BODY(test, tc) \ 50711.77Skamil{ \ 50721.77Skamil \ 50731.77Skamil attach_lwpinfo(threads); \ 50741.77Skamil} 50751.77Skamil 50761.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0) 50771.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1) 50781.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2) 50791.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3) 50801.1Skamil#endif 50811.1Skamil 50821.77Skamil/// ---------------------------------------------------------------------------- 50831.77Skamil 50841.1Skamilstatic void 50851.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught) 50861.1Skamil{ 50871.1Skamil const int exitval = 5; 50881.1Skamil const int sigval = SIGINT; 50891.1Skamil const int sigfaked = SIGTRAP; 50901.1Skamil const int sicodefaked = TRAP_BRKPT; 50911.1Skamil pid_t child, wpid; 50921.1Skamil struct sigaction sa; 50931.1Skamil#if defined(TWAIT_HAVE_STATUS) 50941.1Skamil int status; 50951.1Skamil#endif 50961.1Skamil struct ptrace_siginfo info; 50971.1Skamil memset(&info, 0, sizeof(info)); 50981.1Skamil 50991.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 51001.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 51011.1Skamil if (child == 0) { 51021.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 51031.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 51041.1Skamil 51051.79Skamil sa.sa_sigaction = sah; 51061.1Skamil sa.sa_flags = SA_SIGINFO; 51071.1Skamil sigemptyset(&sa.sa_mask); 51081.1Skamil 51091.79Skamil FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL) 51101.79Skamil != -1); 51111.1Skamil 51121.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 51131.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 51141.1Skamil 51151.79Skamil FORKEE_ASSERT_EQ(*signal_caught, 1); 51161.1Skamil 51171.13Schristos DPRINTF("Before exiting of the child process\n"); 51181.1Skamil _exit(exitval); 51191.1Skamil } 51201.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 51211.1Skamil 51221.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51231.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 51241.1Skamil 51251.1Skamil validate_status_stopped(status, sigval); 51261.1Skamil 51271.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 51281.61Skre SYSCALL_REQUIRE( 51291.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 51301.1Skamil 51311.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 51321.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 51331.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 51341.1Skamil info.psi_siginfo.si_errno); 51351.1Skamil 51361.79Skamil if (faked) { 51371.79Skamil DPRINTF("Before setting new faked signal to signo=%d " 51381.79Skamil "si_code=%d\n", sigfaked, sicodefaked); 51391.79Skamil info.psi_siginfo.si_signo = sigfaked; 51401.79Skamil info.psi_siginfo.si_code = sicodefaked; 51411.79Skamil } 51421.1Skamil 51431.13Schristos DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n"); 51441.61Skre SYSCALL_REQUIRE( 51451.61Skre ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1); 51461.1Skamil 51471.79Skamil if (faked) { 51481.79Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 51491.79Skamil "child\n"); 51501.79Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 51511.79Skamil sizeof(info)) != -1); 51521.1Skamil 51531.79Skamil DPRINTF("Before checking siginfo_t\n"); 51541.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked); 51551.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked); 51561.79Skamil } 51571.1Skamil 51581.13Schristos DPRINTF("Before resuming the child process where it left off and " 51591.1Skamil "without signal to be sent\n"); 51601.79Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 51611.79Skamil faked ? sigfaked : sigval) != -1); 51621.1Skamil 51631.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51641.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 51651.1Skamil 51661.1Skamil validate_status_exited(status, exitval); 51671.1Skamil 51681.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51691.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 51701.1Skamil} 51711.1Skamil 51721.79Skamil#define PTRACE_SIGINFO(test, faked) \ 51731.79SkamilATF_TC(test); \ 51741.79SkamilATF_TC_HEAD(test, tc) \ 51751.79Skamil{ \ 51761.79Skamil atf_tc_set_md_var(tc, "descr", \ 51771.79Skamil "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls" \ 51781.79Skamil "with%s setting signal to new value", faked ? "" : "out"); \ 51791.79Skamil} \ 51801.79Skamil \ 51811.79Skamilstatic int test##_caught = 0; \ 51821.79Skamil \ 51831.79Skamilstatic void \ 51841.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx) \ 51851.79Skamil{ \ 51861.79Skamil if (faked) { \ 51871.79Skamil FORKEE_ASSERT_EQ(sig, SIGTRAP); \ 51881.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP); \ 51891.79Skamil FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT); \ 51901.79Skamil } else { \ 51911.79Skamil FORKEE_ASSERT_EQ(sig, SIGINT); \ 51921.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGINT); \ 51931.79Skamil FORKEE_ASSERT_EQ(info->si_code, SI_LWP); \ 51941.79Skamil } \ 51951.79Skamil \ 51961.79Skamil ++ test##_caught; \ 51971.79Skamil} \ 51981.79Skamil \ 51991.79SkamilATF_TC_BODY(test, tc) \ 52001.79Skamil{ \ 52011.79Skamil \ 52021.79Skamil ptrace_siginfo(faked, test##_sighandler, & test##_caught); \ 52031.79Skamil} 52041.79Skamil 52051.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false) 52061.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true) 52071.79Skamil 52081.79Skamil/// ---------------------------------------------------------------------------- 52091.79Skamil 52101.97Skamilstatic void 52111.97Skamiltraceme_exec(bool masked, bool ignored) 52121.1Skamil{ 52131.1Skamil const int sigval = SIGTRAP; 52141.1Skamil pid_t child, wpid; 52151.1Skamil#if defined(TWAIT_HAVE_STATUS) 52161.1Skamil int status; 52171.1Skamil#endif 52181.97Skamil struct sigaction sa; 52191.97Skamil struct ptrace_siginfo info; 52201.97Skamil sigset_t intmask; 52211.97Skamil struct kinfo_proc2 kp; 52221.97Skamil size_t len = sizeof(kp); 52231.97Skamil 52241.97Skamil int name[6]; 52251.97Skamil const size_t namelen = __arraycount(name); 52261.97Skamil ki_sigset_t kp_sigmask; 52271.97Skamil ki_sigset_t kp_sigignore; 52281.1Skamil 52291.1Skamil memset(&info, 0, sizeof(info)); 52301.1Skamil 52311.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 52321.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 52331.1Skamil if (child == 0) { 52341.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 52351.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 52361.1Skamil 52371.97Skamil if (masked) { 52381.97Skamil sigemptyset(&intmask); 52391.97Skamil sigaddset(&intmask, sigval); 52401.97Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 52411.97Skamil } 52421.97Skamil 52431.97Skamil if (ignored) { 52441.97Skamil memset(&sa, 0, sizeof(sa)); 52451.97Skamil sa.sa_handler = SIG_IGN; 52461.97Skamil sigemptyset(&sa.sa_mask); 52471.97Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 52481.97Skamil } 52491.97Skamil 52501.13Schristos DPRINTF("Before calling execve(2) from child\n"); 52511.1Skamil execlp("/bin/echo", "/bin/echo", NULL); 52521.1Skamil 52531.1Skamil FORKEE_ASSERT(0 && "Not reached"); 52541.1Skamil } 52551.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 52561.1Skamil 52571.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52581.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52591.1Skamil 52601.1Skamil validate_status_stopped(status, sigval); 52611.1Skamil 52621.97Skamil name[0] = CTL_KERN, 52631.97Skamil name[1] = KERN_PROC2, 52641.97Skamil name[2] = KERN_PROC_PID; 52651.97Skamil name[3] = getpid(); 52661.97Skamil name[4] = sizeof(kp); 52671.97Skamil name[5] = 1; 52681.97Skamil 52691.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 52701.97Skamil 52711.97Skamil if (masked) 52721.97Skamil kp_sigmask = kp.p_sigmask; 52731.97Skamil 52741.97Skamil if (ignored) 52751.97Skamil kp_sigignore = kp.p_sigignore; 52761.97Skamil 52771.97Skamil name[3] = getpid(); 52781.97Skamil 52791.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 52801.97Skamil 52811.97Skamil if (masked) { 52821.97Skamil DPRINTF("kp_sigmask=" 52831.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 52841.97Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 52851.97Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 52861.97Skamil 52871.97Skamil DPRINTF("kp.p_sigmask=" 52881.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 52891.97Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 52901.97Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 52911.97Skamil 52921.97Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 52931.97Skamil sizeof(kp_sigmask))); 52941.97Skamil } 52951.97Skamil 52961.97Skamil if (ignored) { 52971.97Skamil DPRINTF("kp_sigignore=" 52981.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 52991.97Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 53001.97Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 53011.97Skamil 53021.97Skamil DPRINTF("kp.p_sigignore=" 53031.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 53041.97Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 53051.97Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 53061.97Skamil 53071.97Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 53081.97Skamil sizeof(kp_sigignore))); 53091.97Skamil } 53101.97Skamil 53111.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 53121.61Skre SYSCALL_REQUIRE( 53131.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 53141.1Skamil 53151.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 53161.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 53171.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 53181.1Skamil info.psi_siginfo.si_errno); 53191.1Skamil 53201.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 53211.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 53221.1Skamil 53231.13Schristos DPRINTF("Before resuming the child process where it left off and " 53241.1Skamil "without signal to be sent\n"); 53251.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 53261.1Skamil 53271.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53281.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 53291.1Skamil 53301.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53311.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 53321.1Skamil} 53331.1Skamil 53341.97Skamil#define TRACEME_EXEC(test, masked, ignored) \ 53351.97SkamilATF_TC(test); \ 53361.97SkamilATF_TC_HEAD(test, tc) \ 53371.97Skamil{ \ 53381.97Skamil atf_tc_set_md_var(tc, "descr", \ 53391.97Skamil "Detect SIGTRAP TRAP_EXEC from " \ 53401.97Skamil "child%s%s", masked ? " with masked signal" : "", \ 53411.97Skamil masked ? " with ignored signal" : ""); \ 53421.97Skamil} \ 53431.97Skamil \ 53441.97SkamilATF_TC_BODY(test, tc) \ 53451.97Skamil{ \ 53461.97Skamil \ 53471.97Skamil traceme_exec(masked, ignored); \ 53481.97Skamil} 53491.97Skamil 53501.97SkamilTRACEME_EXEC(traceme_exec, false, false) 53511.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false) 53521.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true) 53531.97Skamil 53541.82Skamil/// ---------------------------------------------------------------------------- 53551.82Skamil 53561.83Skamilstatic volatile int done; 53571.1Skamil 53581.83Skamilstatic void * 53591.83Skamiltrace_threads_cb(void *arg __unused) 53601.1Skamil{ 53611.1Skamil 53621.83Skamil done++; 53631.83Skamil 53641.83Skamil while (done < 3) 53651.83Skamil continue; 53661.83Skamil 53671.83Skamil return NULL; 53681.1Skamil} 53691.1Skamil 53701.83Skamilstatic void 53711.83Skamiltrace_threads(bool trace_create, bool trace_exit) 53721.1Skamil{ 53731.1Skamil const int sigval = SIGSTOP; 53741.1Skamil pid_t child, wpid; 53751.1Skamil#if defined(TWAIT_HAVE_STATUS) 53761.1Skamil int status; 53771.1Skamil#endif 53781.1Skamil ptrace_state_t state; 53791.1Skamil const int slen = sizeof(state); 53801.1Skamil ptrace_event_t event; 53811.1Skamil const int elen = sizeof(event); 53821.83Skamil struct ptrace_siginfo info; 53831.83Skamil 53841.83Skamil pthread_t t[3]; 53851.83Skamil int rv; 53861.83Skamil size_t n; 53871.1Skamil lwpid_t lid; 53881.83Skamil 53891.83Skamil /* Track created and exited threads */ 53901.83Skamil bool traced_lwps[__arraycount(t)]; 53911.83Skamil 53921.120Skamil if (trace_create || trace_exit) 53931.119Skamil atf_tc_skip("PR kern/51995"); 53941.1Skamil 53951.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 53961.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 53971.1Skamil if (child == 0) { 53981.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 53991.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 54001.1Skamil 54011.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 54021.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 54031.1Skamil 54041.83Skamil for (n = 0; n < __arraycount(t); n++) { 54051.83Skamil rv = pthread_create(&t[n], NULL, trace_threads_cb, 54061.83Skamil NULL); 54071.83Skamil FORKEE_ASSERT(rv == 0); 54081.83Skamil } 54091.1Skamil 54101.83Skamil for (n = 0; n < __arraycount(t); n++) { 54111.83Skamil rv = pthread_join(t[n], NULL); 54121.83Skamil FORKEE_ASSERT(rv == 0); 54131.83Skamil } 54141.1Skamil 54151.83Skamil /* 54161.83Skamil * There is race between _exit() and pthread_join() detaching 54171.83Skamil * a thread. For simplicity kill the process after detecting 54181.83Skamil * LWP events. 54191.83Skamil */ 54201.83Skamil while (true) 54211.83Skamil continue; 54221.1Skamil 54231.83Skamil FORKEE_ASSERT(0 && "Not reached"); 54241.1Skamil } 54251.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 54261.1Skamil 54271.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54281.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 54291.1Skamil 54301.1Skamil validate_status_stopped(status, sigval); 54311.1Skamil 54321.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 54331.83Skamil SYSCALL_REQUIRE( 54341.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 54351.1Skamil 54361.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 54371.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 54381.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 54391.83Skamil info.psi_siginfo.si_errno); 54401.1Skamil 54411.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 54421.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 54431.1Skamil 54441.83Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 54451.83Skamil memset(&event, 0, sizeof(event)); 54461.83Skamil if (trace_create) 54471.83Skamil event.pe_set_event |= PTRACE_LWP_CREATE; 54481.83Skamil if (trace_exit) 54491.83Skamil event.pe_set_event |= PTRACE_LWP_EXIT; 54501.83Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 54511.1Skamil 54521.13Schristos DPRINTF("Before resuming the child process where it left off and " 54531.1Skamil "without signal to be sent\n"); 54541.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 54551.1Skamil 54561.83Skamil memset(traced_lwps, 0, sizeof(traced_lwps)); 54571.1Skamil 54581.83Skamil for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) { 54591.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 54601.83Skamil "SIGTRAP\n", TWAIT_FNAME); 54611.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 54621.83Skamil child); 54631.1Skamil 54641.83Skamil validate_status_stopped(status, SIGTRAP); 54651.1Skamil 54661.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 54671.83Skamil "child\n"); 54681.83Skamil SYSCALL_REQUIRE( 54691.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 54701.1Skamil 54711.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 54721.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 54731.83Skamil "si_errno=%#x\n", 54741.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 54751.83Skamil info.psi_siginfo.si_errno); 54761.1Skamil 54771.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 54781.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 54791.1Skamil 54801.83Skamil SYSCALL_REQUIRE( 54811.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 54821.1Skamil 54831.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 54841.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 54851.1Skamil 54861.83Skamil lid = state.pe_lwp; 54871.83Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 54881.1Skamil 54891.83Skamil traced_lwps[lid - 1] = true; 54901.1Skamil 54911.83Skamil DPRINTF("Before resuming the child process where it left off " 54921.83Skamil "and without signal to be sent\n"); 54931.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 54941.83Skamil } 54951.1Skamil 54961.83Skamil for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) { 54971.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 54981.83Skamil "SIGTRAP\n", TWAIT_FNAME); 54991.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 55001.83Skamil child); 55011.1Skamil 55021.83Skamil validate_status_stopped(status, SIGTRAP); 55031.1Skamil 55041.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 55051.83Skamil "child\n"); 55061.83Skamil SYSCALL_REQUIRE( 55071.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55081.1Skamil 55091.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 55101.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 55111.83Skamil "si_errno=%#x\n", 55121.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 55131.83Skamil info.psi_siginfo.si_errno); 55141.1Skamil 55151.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 55161.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 55171.1Skamil 55181.83Skamil SYSCALL_REQUIRE( 55191.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 55201.1Skamil 55211.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 55221.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 55231.1Skamil 55241.83Skamil lid = state.pe_lwp; 55251.83Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 55261.1Skamil 55271.83Skamil if (trace_create) { 55281.83Skamil ATF_REQUIRE(traced_lwps[lid - 1] == true); 55291.83Skamil traced_lwps[lid - 1] = false; 55301.83Skamil } 55311.1Skamil 55321.83Skamil DPRINTF("Before resuming the child process where it left off " 55331.83Skamil "and without signal to be sent\n"); 55341.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 55351.83Skamil } 55361.1Skamil 55371.83Skamil kill(child, SIGKILL); 55381.1Skamil 55391.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 55401.1Skamil TWAIT_FNAME); 55411.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 55421.1Skamil 55431.83Skamil validate_status_signaled(status, SIGKILL, 0); 55441.1Skamil 55451.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 55461.1Skamil TWAIT_FNAME); 55471.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 55481.1Skamil} 55491.1Skamil 55501.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit) \ 55511.83SkamilATF_TC(test); \ 55521.83SkamilATF_TC_HEAD(test, tc) \ 55531.83Skamil{ \ 55541.83Skamil atf_tc_set_md_var(tc, "descr", \ 55551.83Skamil "Verify spawning threads with%s tracing LWP create and" \ 55561.83Skamil "with%s tracing LWP exit", trace_create ? "" : "out", \ 55571.83Skamil trace_exit ? "" : "out"); \ 55581.83Skamil} \ 55591.83Skamil \ 55601.83SkamilATF_TC_BODY(test, tc) \ 55611.83Skamil{ \ 55621.83Skamil \ 55631.83Skamil trace_threads(trace_create, trace_exit); \ 55641.83Skamil} 55651.83Skamil 55661.119SkamilTRACE_THREADS(trace_thread_nolwpevents, false, false) 55671.119SkamilTRACE_THREADS(trace_thread_lwpexit, false, true) 55681.119SkamilTRACE_THREADS(trace_thread_lwpcreate, true, false) 55691.119SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true) 55701.83Skamil 55711.83Skamil/// ---------------------------------------------------------------------------- 55721.83Skamil 55731.84SkamilATF_TC(signal_mask_unrelated); 55741.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc) 55751.1Skamil{ 55761.1Skamil atf_tc_set_md_var(tc, "descr", 55771.1Skamil "Verify that masking single unrelated signal does not stop tracer " 55781.1Skamil "from catching other signals"); 55791.1Skamil} 55801.1Skamil 55811.84SkamilATF_TC_BODY(signal_mask_unrelated, tc) 55821.1Skamil{ 55831.1Skamil const int exitval = 5; 55841.1Skamil const int sigval = SIGSTOP; 55851.1Skamil const int sigmasked = SIGTRAP; 55861.1Skamil const int signotmasked = SIGINT; 55871.1Skamil pid_t child, wpid; 55881.1Skamil#if defined(TWAIT_HAVE_STATUS) 55891.1Skamil int status; 55901.1Skamil#endif 55911.1Skamil sigset_t intmask; 55921.1Skamil 55931.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 55941.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 55951.1Skamil if (child == 0) { 55961.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 55971.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 55981.1Skamil 55991.1Skamil sigemptyset(&intmask); 56001.1Skamil sigaddset(&intmask, sigmasked); 56011.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 56021.1Skamil 56031.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 56041.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 56051.1Skamil 56061.13Schristos DPRINTF("Before raising %s from child\n", 56071.1Skamil strsignal(signotmasked)); 56081.1Skamil FORKEE_ASSERT(raise(signotmasked) == 0); 56091.1Skamil 56101.13Schristos DPRINTF("Before exiting of the child process\n"); 56111.1Skamil _exit(exitval); 56121.1Skamil } 56131.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 56141.1Skamil 56151.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56161.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56171.1Skamil 56181.1Skamil validate_status_stopped(status, sigval); 56191.1Skamil 56201.13Schristos DPRINTF("Before resuming the child process where it left off and " 56211.1Skamil "without signal to be sent\n"); 56221.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56231.1Skamil 56241.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56251.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56261.1Skamil 56271.1Skamil validate_status_stopped(status, signotmasked); 56281.1Skamil 56291.13Schristos DPRINTF("Before resuming the child process where it left off and " 56301.1Skamil "without signal to be sent\n"); 56311.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56321.1Skamil 56331.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56341.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56351.1Skamil 56361.1Skamil validate_status_exited(status, exitval); 56371.1Skamil 56381.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56391.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 56401.1Skamil} 56411.1Skamil 56421.84Skamil/// ---------------------------------------------------------------------------- 56431.84Skamil 56441.1Skamil#if defined(TWAIT_HAVE_PID) 56451.99Skamilstatic void 56461.99Skamilfork2_body(bool trackfork, bool trackvfork, bool trackvforkdone, bool masked, 56471.99Skamil bool ignored) 56481.1Skamil{ 56491.1Skamil const int exitval = 5; 56501.1Skamil const int exitval2 = 15; 56511.1Skamil const int sigval = SIGSTOP; 56521.99Skamil pid_t child, child2 = 0, wpid; 56531.1Skamil#if defined(TWAIT_HAVE_STATUS) 56541.1Skamil int status; 56551.1Skamil#endif 56561.1Skamil ptrace_state_t state; 56571.1Skamil const int slen = sizeof(state); 56581.1Skamil ptrace_event_t event; 56591.1Skamil const int elen = sizeof(event); 56601.99Skamil pid_t (*fn)(void); 56611.99Skamil struct sigaction sa; 56621.99Skamil struct ptrace_siginfo info; 56631.99Skamil sigset_t intmask; 56641.99Skamil struct kinfo_proc2 kp; 56651.99Skamil size_t len = sizeof(kp); 56661.99Skamil 56671.99Skamil int name[6]; 56681.99Skamil const size_t namelen = __arraycount(name); 56691.99Skamil ki_sigset_t kp_sigmask; 56701.99Skamil ki_sigset_t kp_sigignore; 56711.1Skamil 56721.99Skamil if (trackfork) 56731.99Skamil fn = fork; 56741.99Skamil if (trackvfork || trackvforkdone) 56751.99Skamil fn = vfork; 56761.14Schristos 56771.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 56781.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 56791.1Skamil if (child == 0) { 56801.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 56811.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 56821.1Skamil 56831.99Skamil if (masked) { 56841.99Skamil sigemptyset(&intmask); 56851.99Skamil sigaddset(&intmask, SIGTRAP); 56861.99Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 56871.99Skamil } 56881.99Skamil 56891.99Skamil if (ignored) { 56901.99Skamil memset(&sa, 0, sizeof(sa)); 56911.99Skamil sa.sa_handler = SIG_IGN; 56921.99Skamil sigemptyset(&sa.sa_mask); 56931.99Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 56941.99Skamil } 56951.1Skamil 56961.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 56971.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 56981.1Skamil 56991.99Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 57001.1Skamil 57011.1Skamil if (child2 == 0) 57021.1Skamil _exit(exitval2); 57031.1Skamil 57041.1Skamil FORKEE_REQUIRE_SUCCESS 57051.99Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 57061.1Skamil 57071.1Skamil forkee_status_exited(status, exitval2); 57081.1Skamil 57091.13Schristos DPRINTF("Before exiting of the child process\n"); 57101.1Skamil _exit(exitval); 57111.1Skamil } 57121.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 57131.1Skamil 57141.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57151.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57161.1Skamil 57171.1Skamil validate_status_stopped(status, sigval); 57181.1Skamil 57191.99Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 57201.99Skamil SYSCALL_REQUIRE( 57211.99Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 57221.99Skamil 57231.99Skamil DPRINTF("Before checking siginfo_t\n"); 57241.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 57251.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 57261.1Skamil 57271.99Skamil name[0] = CTL_KERN, 57281.99Skamil name[1] = KERN_PROC2, 57291.99Skamil name[2] = KERN_PROC_PID; 57301.99Skamil name[3] = child; 57311.99Skamil name[4] = sizeof(kp); 57321.99Skamil name[5] = 1; 57331.1Skamil 57341.99Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 57351.1Skamil 57361.99Skamil if (masked) 57371.99Skamil kp_sigmask = kp.p_sigmask; 57381.1Skamil 57391.99Skamil if (ignored) 57401.99Skamil kp_sigignore = kp.p_sigignore; 57411.1Skamil 57421.99Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 57431.99Skamil trackfork ? "|PTRACE_FORK" : "", 57441.99Skamil trackvfork ? "|PTRACE_VFORK" : "", 57451.99Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 57461.99Skamil event.pe_set_event = 0; 57471.99Skamil if (trackfork) 57481.99Skamil event.pe_set_event |= PTRACE_FORK; 57491.99Skamil if (trackvfork) 57501.99Skamil event.pe_set_event |= PTRACE_VFORK; 57511.99Skamil if (trackvforkdone) 57521.99Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 57531.99Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 57541.1Skamil 57551.99Skamil DPRINTF("Before resuming the child process where it left off and " 57561.99Skamil "without signal to be sent\n"); 57571.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 57581.1Skamil 57591.99Skamil if (trackfork || trackvfork) { 57601.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 57611.99Skamil child); 57621.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 57631.99Skamil child); 57641.1Skamil 57651.99Skamil validate_status_stopped(status, SIGTRAP); 57661.1Skamil 57671.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 57681.1Skamil 57691.99Skamil if (masked) { 57701.99Skamil DPRINTF("kp_sigmask=" 57711.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 57721.99Skamil PRIx32 "\n", 57731.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 57741.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 57751.1Skamil 57761.99Skamil DPRINTF("kp.p_sigmask=" 57771.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 57781.99Skamil PRIx32 "\n", 57791.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 57801.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 57811.1Skamil 57821.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 57831.99Skamil sizeof(kp_sigmask))); 57841.99Skamil } 57851.1Skamil 57861.99Skamil if (ignored) { 57871.99Skamil DPRINTF("kp_sigignore=" 57881.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 57891.99Skamil PRIx32 "\n", 57901.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 57911.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 57921.1Skamil 57931.99Skamil DPRINTF("kp.p_sigignore=" 57941.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 57951.99Skamil PRIx32 "\n", 57961.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 57971.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 57981.1Skamil 57991.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 58001.99Skamil sizeof(kp_sigignore))); 58011.99Skamil } 58021.1Skamil 58031.99Skamil SYSCALL_REQUIRE( 58041.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 58051.99Skamil if (trackfork) { 58061.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 58071.99Skamil PTRACE_FORK); 58081.99Skamil } 58091.99Skamil if (trackvfork) { 58101.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 58111.99Skamil PTRACE_VFORK); 58121.99Skamil } 58131.1Skamil 58141.99Skamil child2 = state.pe_other_pid; 58151.99Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 58161.1Skamil 58171.99Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 58181.99Skamil "%d\n", TWAIT_FNAME, child2, child); 58191.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 58201.99Skamil child2); 58211.1Skamil 58221.99Skamil validate_status_stopped(status, SIGTRAP); 58231.1Skamil 58241.99Skamil name[3] = child2; 58251.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 58261.1Skamil 58271.99Skamil if (masked) { 58281.99Skamil DPRINTF("kp_sigmask=" 58291.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58301.99Skamil PRIx32 "\n", 58311.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 58321.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 58331.1Skamil 58341.99Skamil DPRINTF("kp.p_sigmask=" 58351.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58361.99Skamil PRIx32 "\n", 58371.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 58381.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 58391.14Schristos 58401.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 58411.99Skamil sizeof(kp_sigmask))); 58421.99Skamil } 58431.1Skamil 58441.99Skamil if (ignored) { 58451.99Skamil DPRINTF("kp_sigignore=" 58461.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58471.99Skamil PRIx32 "\n", 58481.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 58491.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 58501.1Skamil 58511.99Skamil DPRINTF("kp.p_sigignore=" 58521.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58531.99Skamil PRIx32 "\n", 58541.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 58551.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 58561.1Skamil 58571.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 58581.99Skamil sizeof(kp_sigignore))); 58591.99Skamil } 58601.1Skamil 58611.99Skamil SYSCALL_REQUIRE( 58621.99Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 58631.99Skamil if (trackfork) { 58641.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 58651.99Skamil PTRACE_FORK); 58661.99Skamil } 58671.99Skamil if (trackvfork) { 58681.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 58691.99Skamil PTRACE_VFORK); 58701.99Skamil } 58711.1Skamil 58721.99Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 58731.1Skamil 58741.99Skamil DPRINTF("Before resuming the forkee process where it left off " 58751.99Skamil "and without signal to be sent\n"); 58761.99Skamil SYSCALL_REQUIRE( 58771.99Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 58781.1Skamil 58791.99Skamil DPRINTF("Before resuming the child process where it left off " 58801.99Skamil "and without signal to be sent\n"); 58811.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 58821.1Skamil } 58831.1Skamil 58841.99Skamil if (trackvforkdone) { 58851.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 58861.99Skamil child); 58871.99Skamil TWAIT_REQUIRE_SUCCESS( 58881.99Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 58891.1Skamil 58901.99Skamil validate_status_stopped(status, SIGTRAP); 58911.1Skamil 58921.99Skamil name[3] = child; 58931.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 58941.1Skamil 58951.102Skamil /* 58961.102Skamil * SIGCHLD is now pending in the signal queue and 58971.102Skamil * the kernel presents it to userland as a masked signal. 58981.102Skamil */ 58991.102Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 59001.102Skamil 59011.99Skamil if (masked) { 59021.99Skamil DPRINTF("kp_sigmask=" 59031.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59041.99Skamil PRIx32 "\n", 59051.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 59061.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 59071.1Skamil 59081.99Skamil DPRINTF("kp.p_sigmask=" 59091.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59101.99Skamil PRIx32 "\n", 59111.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 59121.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 59131.1Skamil 59141.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 59151.99Skamil sizeof(kp_sigmask))); 59161.99Skamil } 59171.1Skamil 59181.99Skamil if (ignored) { 59191.99Skamil DPRINTF("kp_sigignore=" 59201.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59211.99Skamil PRIx32 "\n", 59221.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 59231.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 59241.1Skamil 59251.99Skamil DPRINTF("kp.p_sigignore=" 59261.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59271.99Skamil PRIx32 "\n", 59281.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 59291.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 59301.1Skamil 59311.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 59321.99Skamil sizeof(kp_sigignore))); 59331.99Skamil } 59341.1Skamil 59351.99Skamil SYSCALL_REQUIRE( 59361.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 59371.99Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 59381.1Skamil 59391.99Skamil child2 = state.pe_other_pid; 59401.99Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 59411.99Skamil child2); 59421.1Skamil 59431.99Skamil DPRINTF("Before resuming the child process where it left off " 59441.99Skamil "and without signal to be sent\n"); 59451.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 59461.99Skamil } 59471.1Skamil 59481.99Skamil if (trackfork || trackvfork) { 59491.99Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 59501.99Skamil "\n", TWAIT_FNAME); 59511.99Skamil TWAIT_REQUIRE_SUCCESS( 59521.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 59531.1Skamil 59541.99Skamil validate_status_exited(status, exitval2); 59551.1Skamil 59561.99Skamil DPRINTF("Before calling %s() for the forkee - expected no " 59571.99Skamil "process\n", TWAIT_FNAME); 59581.99Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 59591.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 59601.99Skamil } 59611.1Skamil 59621.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 59631.1Skamil "SIGCHLD\n", TWAIT_FNAME); 59641.57Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 59651.1Skamil 59661.1Skamil validate_status_stopped(status, SIGCHLD); 59671.1Skamil 59681.57Skamil DPRINTF("Before resuming the child process where it left off and " 59691.1Skamil "without signal to be sent\n"); 59701.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 59711.1Skamil 59721.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 59731.1Skamil TWAIT_FNAME); 59741.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 59751.1Skamil 59761.1Skamil validate_status_exited(status, exitval); 59771.1Skamil 59781.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 59791.57Skamil TWAIT_FNAME); 59801.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 59811.1Skamil} 59821.1Skamil 59831.99Skamil#define FORK2_TEST(name,trackfork,trackvfork,trackvforkdone, \ 59841.99Skamil masked,ignored) \ 59851.99SkamilATF_TC(name); \ 59861.99SkamilATF_TC_HEAD(name, tc) \ 59871.99Skamil{ \ 59881.99Skamil atf_tc_set_md_var(tc, "descr", "Verify that %s%s%s is caught " \ 59891.99Skamil "regardless of signal %s%s", \ 59901.99Skamil trackfork ? "PTRACE_FORK" : "", \ 59911.99Skamil trackvfork ? "PTRACE_VFORK" : "", \ 59921.99Skamil trackvforkdone ? "PTRACE_VFORK_DONE" : "", \ 59931.99Skamil masked ? "masked" : "", ignored ? "ignored" : ""); \ 59941.99Skamil} \ 59951.99Skamil \ 59961.99SkamilATF_TC_BODY(name, tc) \ 59971.99Skamil{ \ 59981.99Skamil \ 59991.99Skamil fork2_body(trackfork, trackvfork, trackvforkdone, masked, \ 60001.99Skamil ignored); \ 60011.1Skamil} 60021.1Skamil 60031.99SkamilFORK2_TEST(fork_singalmasked, true, false, false, true, false) 60041.99SkamilFORK2_TEST(fork_singalignored, true, false, false, false, true) 60051.110Skamil#if TEST_VFORK_ENABLED 60061.99SkamilFORK2_TEST(vfork_singalmasked, false, true, false, true, false) 60071.99SkamilFORK2_TEST(vfork_singalignored, false, true, false, false, true) 60081.99SkamilFORK2_TEST(vforkdone_singalmasked, false, false, true, true, false) 60091.99SkamilFORK2_TEST(vforkdone_singalignored, false, false, true, false, true) 60101.1Skamil#endif 60111.110Skamil#endif 60121.1Skamil 60131.99Skamil/// ---------------------------------------------------------------------------- 60141.1Skamil 60151.83Skamilvolatile lwpid_t the_lwp_id = 0; 60161.83Skamil 60171.83Skamilstatic void 60181.83Skamillwp_main_func(void *arg) 60191.83Skamil{ 60201.83Skamil the_lwp_id = _lwp_self(); 60211.83Skamil _lwp_exit(); 60221.83Skamil} 60231.83Skamil 60241.1SkamilATF_TC(signal9); 60251.1SkamilATF_TC_HEAD(signal9, tc) 60261.1Skamil{ 60271.1Skamil atf_tc_set_md_var(tc, "descr", 60281.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 60291.1Skamil "catching PTRACE_LWP_CREATE breakpoint"); 60301.1Skamil} 60311.1Skamil 60321.1SkamilATF_TC_BODY(signal9, tc) 60331.1Skamil{ 60341.1Skamil const int exitval = 5; 60351.1Skamil const int sigval = SIGSTOP; 60361.1Skamil const int sigmasked = SIGTRAP; 60371.1Skamil pid_t child, wpid; 60381.1Skamil#if defined(TWAIT_HAVE_STATUS) 60391.1Skamil int status; 60401.1Skamil#endif 60411.1Skamil sigset_t intmask; 60421.1Skamil ptrace_state_t state; 60431.1Skamil const int slen = sizeof(state); 60441.1Skamil ptrace_event_t event; 60451.1Skamil const int elen = sizeof(event); 60461.1Skamil ucontext_t uc; 60471.1Skamil lwpid_t lid; 60481.1Skamil static const size_t ssize = 16*1024; 60491.1Skamil void *stack; 60501.1Skamil 60511.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 60521.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 60531.1Skamil if (child == 0) { 60541.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 60551.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 60561.1Skamil 60571.1Skamil sigemptyset(&intmask); 60581.1Skamil sigaddset(&intmask, sigmasked); 60591.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 60601.1Skamil 60611.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 60621.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 60631.1Skamil 60641.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 60651.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 60661.1Skamil 60671.13Schristos DPRINTF("Before making context for new lwp in child\n"); 60681.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 60691.1Skamil 60701.13Schristos DPRINTF("Before creating new in child\n"); 60711.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 60721.1Skamil 60731.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 60741.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 60751.1Skamil 60761.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 60771.1Skamil "are the same\n", lid, the_lwp_id); 60781.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 60791.1Skamil 60801.13Schristos DPRINTF("Before exiting of the child process\n"); 60811.1Skamil _exit(exitval); 60821.1Skamil } 60831.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 60841.1Skamil 60851.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 60861.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60871.1Skamil 60881.1Skamil validate_status_stopped(status, sigval); 60891.1Skamil 60901.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 60911.1Skamil event.pe_set_event = PTRACE_LWP_CREATE; 60921.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 60931.1Skamil 60941.13Schristos DPRINTF("Before resuming the child process where it left off and " 60951.1Skamil "without signal to be sent\n"); 60961.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60971.1Skamil 60981.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 60991.1Skamil "SIGTRAP\n", TWAIT_FNAME); 61001.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61011.1Skamil 61021.1Skamil validate_status_stopped(status, sigmasked); 61031.1Skamil 61041.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 61051.1Skamil 61061.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE); 61071.1Skamil 61081.1Skamil lid = state.pe_lwp; 61091.13Schristos DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 61101.1Skamil 61111.13Schristos DPRINTF("Before resuming the child process where it left off and " 61121.1Skamil "without signal to be sent\n"); 61131.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 61141.1Skamil 61151.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 61161.1Skamil TWAIT_FNAME); 61171.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61181.1Skamil 61191.1Skamil validate_status_exited(status, exitval); 61201.1Skamil 61211.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 61221.1Skamil TWAIT_FNAME); 61231.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 61241.1Skamil} 61251.1Skamil 61261.1SkamilATF_TC(signal10); 61271.1SkamilATF_TC_HEAD(signal10, tc) 61281.1Skamil{ 61291.1Skamil atf_tc_set_md_var(tc, "descr", 61301.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 61311.1Skamil "catching PTRACE_LWP_EXIT breakpoint"); 61321.1Skamil} 61331.1Skamil 61341.1SkamilATF_TC_BODY(signal10, tc) 61351.1Skamil{ 61361.1Skamil const int exitval = 5; 61371.1Skamil const int sigval = SIGSTOP; 61381.1Skamil const int sigmasked = SIGTRAP; 61391.1Skamil pid_t child, wpid; 61401.1Skamil#if defined(TWAIT_HAVE_STATUS) 61411.1Skamil int status; 61421.1Skamil#endif 61431.1Skamil sigset_t intmask; 61441.1Skamil ptrace_state_t state; 61451.1Skamil const int slen = sizeof(state); 61461.1Skamil ptrace_event_t event; 61471.1Skamil const int elen = sizeof(event); 61481.1Skamil ucontext_t uc; 61491.1Skamil lwpid_t lid; 61501.1Skamil static const size_t ssize = 16*1024; 61511.1Skamil void *stack; 61521.1Skamil 61531.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 61541.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 61551.1Skamil if (child == 0) { 61561.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 61571.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 61581.1Skamil 61591.1Skamil sigemptyset(&intmask); 61601.1Skamil sigaddset(&intmask, sigmasked); 61611.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 61621.1Skamil 61631.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 61641.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 61651.1Skamil 61661.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 61671.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 61681.1Skamil 61691.13Schristos DPRINTF("Before making context for new lwp in child\n"); 61701.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 61711.1Skamil 61721.13Schristos DPRINTF("Before creating new in child\n"); 61731.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 61741.1Skamil 61751.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 61761.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 61771.1Skamil 61781.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 61791.1Skamil "are the same\n", lid, the_lwp_id); 61801.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 61811.1Skamil 61821.13Schristos DPRINTF("Before exiting of the child process\n"); 61831.1Skamil _exit(exitval); 61841.1Skamil } 61851.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 61861.1Skamil 61871.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 61881.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61891.1Skamil 61901.1Skamil validate_status_stopped(status, sigval); 61911.1Skamil 61921.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 61931.1Skamil event.pe_set_event = PTRACE_LWP_EXIT; 61941.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 61951.1Skamil 61961.13Schristos DPRINTF("Before resuming the child process where it left off and " 61971.1Skamil "without signal to be sent\n"); 61981.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 61991.1Skamil 62001.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 62011.1Skamil "SIGTRAP\n", TWAIT_FNAME); 62021.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62031.1Skamil 62041.1Skamil validate_status_stopped(status, sigmasked); 62051.1Skamil 62061.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 62071.1Skamil 62081.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT); 62091.1Skamil 62101.1Skamil lid = state.pe_lwp; 62111.13Schristos DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 62121.1Skamil 62131.13Schristos DPRINTF("Before resuming the child process where it left off and " 62141.1Skamil "without signal to be sent\n"); 62151.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 62161.1Skamil 62171.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 62181.1Skamil TWAIT_FNAME); 62191.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62201.1Skamil 62211.1Skamil validate_status_exited(status, exitval); 62221.1Skamil 62231.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 62241.1Skamil TWAIT_FNAME); 62251.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 62261.1Skamil} 62271.1Skamil 62281.1Skamilstatic void 62291.1Skamillwp_main_stop(void *arg) 62301.1Skamil{ 62311.1Skamil the_lwp_id = _lwp_self(); 62321.1Skamil 62331.1Skamil raise(SIGTRAP); 62341.1Skamil 62351.1Skamil _lwp_exit(); 62361.1Skamil} 62371.1Skamil 62381.1SkamilATF_TC(suspend1); 62391.1SkamilATF_TC_HEAD(suspend1, tc) 62401.1Skamil{ 62411.1Skamil atf_tc_set_md_var(tc, "descr", 62421.1Skamil "Verify that a thread can be suspended by a debugger and later " 62431.1Skamil "resumed by a tracee"); 62441.1Skamil} 62451.1Skamil 62461.1SkamilATF_TC_BODY(suspend1, tc) 62471.1Skamil{ 62481.1Skamil const int exitval = 5; 62491.1Skamil const int sigval = SIGSTOP; 62501.1Skamil pid_t child, wpid; 62511.1Skamil#if defined(TWAIT_HAVE_STATUS) 62521.1Skamil int status; 62531.1Skamil#endif 62541.1Skamil ucontext_t uc; 62551.1Skamil lwpid_t lid; 62561.1Skamil static const size_t ssize = 16*1024; 62571.1Skamil void *stack; 62581.1Skamil struct ptrace_lwpinfo pl; 62591.1Skamil struct ptrace_siginfo psi; 62601.1Skamil volatile int go = 0; 62611.1Skamil 62621.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 62631.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 62641.1Skamil if (child == 0) { 62651.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 62661.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 62671.1Skamil 62681.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 62691.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 62701.1Skamil 62711.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 62721.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 62731.1Skamil 62741.13Schristos DPRINTF("Before making context for new lwp in child\n"); 62751.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 62761.1Skamil 62771.13Schristos DPRINTF("Before creating new in child\n"); 62781.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 62791.1Skamil 62801.1Skamil while (go == 0) 62811.1Skamil continue; 62821.1Skamil 62831.1Skamil raise(SIGINT); 62841.1Skamil 62851.1Skamil FORKEE_ASSERT(_lwp_continue(lid) == 0); 62861.1Skamil 62871.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 62881.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 62891.1Skamil 62901.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 62911.1Skamil "are the same\n", lid, the_lwp_id); 62921.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 62931.1Skamil 62941.13Schristos DPRINTF("Before exiting of the child process\n"); 62951.1Skamil _exit(exitval); 62961.1Skamil } 62971.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 62981.1Skamil 62991.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 63001.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63011.1Skamil 63021.1Skamil validate_status_stopped(status, sigval); 63031.1Skamil 63041.13Schristos DPRINTF("Before resuming the child process where it left off and " 63051.1Skamil "without signal to be sent\n"); 63061.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63071.1Skamil 63081.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 63091.1Skamil "SIGTRAP\n", TWAIT_FNAME); 63101.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63111.1Skamil 63121.1Skamil validate_status_stopped(status, SIGTRAP); 63131.1Skamil 63141.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 63151.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 63161.1Skamil 63171.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 63181.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 63191.1Skamil 63201.13Schristos DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n", 63211.1Skamil child, getpid()); 63221.13Schristos SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1); 63231.1Skamil 63241.13Schristos DPRINTF("Before resuming the child process where it left off and " 63251.1Skamil "without signal to be sent\n"); 63261.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63271.1Skamil 63281.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 63291.1Skamil "SIGINT\n", TWAIT_FNAME); 63301.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63311.1Skamil 63321.1Skamil validate_status_stopped(status, SIGINT); 63331.1Skamil 63341.1Skamil pl.pl_lwpid = 0; 63351.1Skamil 63361.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 63371.1Skamil while (pl.pl_lwpid != 0) { 63381.1Skamil 63391.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 63401.1Skamil switch (pl.pl_lwpid) { 63411.1Skamil case 1: 63421.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 63431.1Skamil break; 63441.1Skamil case 2: 63451.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 63461.1Skamil break; 63471.1Skamil } 63481.1Skamil } 63491.1Skamil 63501.13Schristos DPRINTF("Before resuming the child process where it left off and " 63511.1Skamil "without signal to be sent\n"); 63521.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63531.1Skamil 63541.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 63551.1Skamil TWAIT_FNAME); 63561.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63571.1Skamil 63581.1Skamil validate_status_exited(status, exitval); 63591.1Skamil 63601.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 63611.1Skamil TWAIT_FNAME); 63621.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 63631.1Skamil} 63641.1Skamil 63651.1SkamilATF_TC(suspend2); 63661.1SkamilATF_TC_HEAD(suspend2, tc) 63671.1Skamil{ 63681.1Skamil atf_tc_set_md_var(tc, "descr", 63691.1Skamil "Verify that the while the only thread within a process is " 63701.1Skamil "suspended, the whole process cannot be unstopped"); 63711.1Skamil} 63721.1Skamil 63731.1SkamilATF_TC_BODY(suspend2, tc) 63741.1Skamil{ 63751.1Skamil const int exitval = 5; 63761.1Skamil const int sigval = SIGSTOP; 63771.1Skamil pid_t child, wpid; 63781.1Skamil#if defined(TWAIT_HAVE_STATUS) 63791.1Skamil int status; 63801.1Skamil#endif 63811.1Skamil struct ptrace_siginfo psi; 63821.1Skamil 63831.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 63841.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 63851.1Skamil if (child == 0) { 63861.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 63871.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 63881.1Skamil 63891.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 63901.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 63911.1Skamil 63921.13Schristos DPRINTF("Before exiting of the child process\n"); 63931.1Skamil _exit(exitval); 63941.1Skamil } 63951.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 63961.1Skamil 63971.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 63981.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63991.1Skamil 64001.1Skamil validate_status_stopped(status, sigval); 64011.1Skamil 64021.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 64031.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 64041.1Skamil 64051.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 64061.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 64071.1Skamil 64081.13Schristos DPRINTF("Before resuming the child process where it left off and " 64091.1Skamil "without signal to be sent\n"); 64101.1Skamil ATF_REQUIRE_ERRNO(EDEADLK, 64111.1Skamil ptrace(PT_CONTINUE, child, (void *)1, 0) == -1); 64121.1Skamil 64131.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 64141.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 64151.1Skamil 64161.13Schristos DPRINTF("Before resuming the child process where it left off and " 64171.1Skamil "without signal to be sent\n"); 64181.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64191.1Skamil 64201.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 64211.1Skamil TWAIT_FNAME); 64221.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64231.1Skamil 64241.1Skamil validate_status_exited(status, exitval); 64251.1Skamil 64261.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 64271.1Skamil TWAIT_FNAME); 64281.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 64291.1Skamil} 64301.1Skamil 64311.1SkamilATF_TC(resume1); 64321.1SkamilATF_TC_HEAD(resume1, tc) 64331.1Skamil{ 64341.1Skamil atf_tc_set_md_var(tc, "descr", 64351.1Skamil "Verify that a thread can be suspended by a debugger and later " 64361.1Skamil "resumed by the debugger"); 64371.1Skamil} 64381.1Skamil 64391.1SkamilATF_TC_BODY(resume1, tc) 64401.1Skamil{ 64411.1Skamil struct msg_fds fds; 64421.1Skamil const int exitval = 5; 64431.1Skamil const int sigval = SIGSTOP; 64441.1Skamil pid_t child, wpid; 64451.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 64461.1Skamil#if defined(TWAIT_HAVE_STATUS) 64471.1Skamil int status; 64481.1Skamil#endif 64491.1Skamil ucontext_t uc; 64501.1Skamil lwpid_t lid; 64511.1Skamil static const size_t ssize = 16*1024; 64521.1Skamil void *stack; 64531.1Skamil struct ptrace_lwpinfo pl; 64541.1Skamil struct ptrace_siginfo psi; 64551.1Skamil 64561.13Schristos SYSCALL_REQUIRE(msg_open(&fds) == 0); 64571.1Skamil 64581.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 64591.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 64601.1Skamil if (child == 0) { 64611.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 64621.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 64631.1Skamil 64641.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 64651.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 64661.1Skamil 64671.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 64681.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 64691.1Skamil 64701.13Schristos DPRINTF("Before making context for new lwp in child\n"); 64711.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 64721.1Skamil 64731.13Schristos DPRINTF("Before creating new in child\n"); 64741.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 64751.1Skamil 64761.1Skamil CHILD_TO_PARENT("Message", fds, msg); 64771.1Skamil 64781.1Skamil raise(SIGINT); 64791.1Skamil 64801.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 64811.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 64821.1Skamil 64831.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 64841.1Skamil "are the same\n", lid, the_lwp_id); 64851.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 64861.1Skamil 64871.13Schristos DPRINTF("Before exiting of the child process\n"); 64881.1Skamil _exit(exitval); 64891.1Skamil } 64901.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 64911.1Skamil 64921.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 64931.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64941.1Skamil 64951.1Skamil validate_status_stopped(status, sigval); 64961.1Skamil 64971.13Schristos DPRINTF("Before resuming the child process where it left off and " 64981.1Skamil "without signal to be sent\n"); 64991.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65001.1Skamil 65011.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 65021.1Skamil "SIGTRAP\n", TWAIT_FNAME); 65031.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65041.1Skamil 65051.1Skamil validate_status_stopped(status, SIGTRAP); 65061.1Skamil 65071.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 65081.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 65091.1Skamil 65101.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 65111.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 65121.1Skamil 65131.1Skamil PARENT_FROM_CHILD("Message", fds, msg); 65141.1Skamil 65151.13Schristos DPRINTF("Before resuming the child process where it left off and " 65161.1Skamil "without signal to be sent\n"); 65171.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65181.1Skamil 65191.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 65201.1Skamil "SIGINT\n", TWAIT_FNAME); 65211.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65221.1Skamil 65231.1Skamil validate_status_stopped(status, SIGINT); 65241.1Skamil 65251.1Skamil pl.pl_lwpid = 0; 65261.1Skamil 65271.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 65281.1Skamil while (pl.pl_lwpid != 0) { 65291.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 65301.1Skamil switch (pl.pl_lwpid) { 65311.1Skamil case 1: 65321.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 65331.1Skamil break; 65341.1Skamil case 2: 65351.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 65361.1Skamil break; 65371.1Skamil } 65381.1Skamil } 65391.1Skamil 65401.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 65411.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 65421.1Skamil 65431.13Schristos DPRINTF("Before resuming the child process where it left off and " 65441.1Skamil "without signal to be sent\n"); 65451.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65461.1Skamil 65471.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 65481.1Skamil TWAIT_FNAME); 65491.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65501.1Skamil 65511.1Skamil validate_status_exited(status, exitval); 65521.1Skamil 65531.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 65541.1Skamil TWAIT_FNAME); 65551.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 65561.1Skamil 65571.1Skamil msg_close(&fds); 65581.1Skamil} 65591.1Skamil 65601.1SkamilATF_TC(syscall1); 65611.1SkamilATF_TC_HEAD(syscall1, tc) 65621.1Skamil{ 65631.1Skamil atf_tc_set_md_var(tc, "descr", 65641.1Skamil "Verify that getpid(2) can be traced with PT_SYSCALL"); 65651.1Skamil} 65661.1Skamil 65671.1SkamilATF_TC_BODY(syscall1, tc) 65681.1Skamil{ 65691.1Skamil const int exitval = 5; 65701.1Skamil const int sigval = SIGSTOP; 65711.1Skamil pid_t child, wpid; 65721.1Skamil#if defined(TWAIT_HAVE_STATUS) 65731.1Skamil int status; 65741.1Skamil#endif 65751.1Skamil struct ptrace_siginfo info; 65761.1Skamil memset(&info, 0, sizeof(info)); 65771.1Skamil 65781.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 65791.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 65801.1Skamil if (child == 0) { 65811.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 65821.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 65831.1Skamil 65841.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 65851.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 65861.1Skamil 65871.1Skamil syscall(SYS_getpid); 65881.1Skamil 65891.13Schristos DPRINTF("Before exiting of the child process\n"); 65901.1Skamil _exit(exitval); 65911.1Skamil } 65921.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 65931.1Skamil 65941.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65951.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65961.1Skamil 65971.1Skamil validate_status_stopped(status, sigval); 65981.1Skamil 65991.13Schristos DPRINTF("Before resuming the child process where it left off and " 66001.1Skamil "without signal to be sent\n"); 66011.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 66021.1Skamil 66031.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66041.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66051.1Skamil 66061.1Skamil validate_status_stopped(status, SIGTRAP); 66071.1Skamil 66081.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 66091.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 66101.1Skamil 66111.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 66121.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 66131.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 66141.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE); 66151.1Skamil 66161.13Schristos DPRINTF("Before resuming the child process where it left off and " 66171.1Skamil "without signal to be sent\n"); 66181.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 66191.1Skamil 66201.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66211.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66221.1Skamil 66231.1Skamil validate_status_stopped(status, SIGTRAP); 66241.1Skamil 66251.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 66261.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 66271.1Skamil 66281.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 66291.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 66301.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 66311.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX); 66321.1Skamil 66331.13Schristos DPRINTF("Before resuming the child process where it left off and " 66341.1Skamil "without signal to be sent\n"); 66351.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66361.1Skamil 66371.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66381.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66391.1Skamil 66401.1Skamil validate_status_exited(status, exitval); 66411.1Skamil 66421.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66431.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 66441.1Skamil} 66451.1Skamil 66461.1SkamilATF_TC(syscallemu1); 66471.1SkamilATF_TC_HEAD(syscallemu1, tc) 66481.1Skamil{ 66491.1Skamil atf_tc_set_md_var(tc, "descr", 66501.1Skamil "Verify that exit(2) can be intercepted with PT_SYSCALLEMU"); 66511.1Skamil} 66521.1Skamil 66531.1SkamilATF_TC_BODY(syscallemu1, tc) 66541.1Skamil{ 66551.1Skamil const int exitval = 5; 66561.1Skamil const int sigval = SIGSTOP; 66571.1Skamil pid_t child, wpid; 66581.1Skamil#if defined(TWAIT_HAVE_STATUS) 66591.1Skamil int status; 66601.1Skamil#endif 66611.1Skamil 66621.6Skamil#if defined(__sparc__) && !defined(__sparc64__) 66631.6Skamil /* syscallemu does not work on sparc (32-bit) */ 66641.6Skamil atf_tc_expect_fail("PR kern/52166"); 66651.6Skamil#endif 66661.6Skamil 66671.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 66681.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 66691.1Skamil if (child == 0) { 66701.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 66711.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 66721.1Skamil 66731.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 66741.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 66751.1Skamil 66761.1Skamil syscall(SYS_exit, 100); 66771.1Skamil 66781.13Schristos DPRINTF("Before exiting of the child process\n"); 66791.1Skamil _exit(exitval); 66801.1Skamil } 66811.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 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, sigval); 66871.1Skamil 66881.13Schristos DPRINTF("Before resuming the child process where it left off and " 66891.1Skamil "without signal to be sent\n"); 66901.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 66911.1Skamil 66921.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66931.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66941.1Skamil 66951.1Skamil validate_status_stopped(status, SIGTRAP); 66961.1Skamil 66971.13Schristos DPRINTF("Set SYSCALLEMU for intercepted syscall\n"); 66981.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1); 66991.1Skamil 67001.13Schristos DPRINTF("Before resuming the child process where it left off and " 67011.1Skamil "without signal to be sent\n"); 67021.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 67031.1Skamil 67041.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67051.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67061.1Skamil 67071.1Skamil validate_status_stopped(status, SIGTRAP); 67081.1Skamil 67091.13Schristos DPRINTF("Before resuming the child process where it left off and " 67101.1Skamil "without signal to be sent\n"); 67111.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 67121.1Skamil 67131.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67141.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67151.1Skamil 67161.1Skamil validate_status_exited(status, exitval); 67171.1Skamil 67181.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67191.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 67201.1Skamil} 67211.1Skamil 67221.103Skamil/// ---------------------------------------------------------------------------- 67231.103Skamil 67241.106Skamilstatic void 67251.106Skamilclone_body(int flags, bool trackfork, bool trackvfork, 67261.106Skamil bool trackvforkdone) 67271.106Skamil{ 67281.106Skamil const int exitval = 5; 67291.106Skamil const int exitval2 = 15; 67301.106Skamil const int sigval = SIGSTOP; 67311.106Skamil pid_t child, child2 = 0, wpid; 67321.106Skamil#if defined(TWAIT_HAVE_STATUS) 67331.106Skamil int status; 67341.106Skamil#endif 67351.106Skamil ptrace_state_t state; 67361.106Skamil const int slen = sizeof(state); 67371.106Skamil ptrace_event_t event; 67381.106Skamil const int elen = sizeof(event); 67391.106Skamil 67401.106Skamil const size_t stack_size = 1024 * 1024; 67411.106Skamil void *stack, *stack_base; 67421.106Skamil 67431.106Skamil stack = malloc(stack_size); 67441.106Skamil ATF_REQUIRE(stack != NULL); 67451.106Skamil 67461.106Skamil#ifdef __MACHINE_STACK_GROWS_UP 67471.106Skamil stack_base = stack; 67481.106Skamil#else 67491.106Skamil stack_base = (char *)stack + stack_size; 67501.106Skamil#endif 67511.106Skamil 67521.106Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 67531.106Skamil SYSCALL_REQUIRE((child = fork()) != -1); 67541.106Skamil if (child == 0) { 67551.106Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 67561.106Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 67571.106Skamil 67581.106Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 67591.106Skamil FORKEE_ASSERT(raise(sigval) == 0); 67601.106Skamil 67611.106Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 67621.106Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 67631.106Skamil 67641.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 67651.106Skamil child2); 67661.106Skamil 67671.106Skamil // XXX WALLSIG? 67681.106Skamil FORKEE_REQUIRE_SUCCESS 67691.106Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 67701.106Skamil 67711.106Skamil forkee_status_exited(status, exitval2); 67721.106Skamil 67731.106Skamil DPRINTF("Before exiting of the child process\n"); 67741.106Skamil _exit(exitval); 67751.106Skamil } 67761.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 67771.106Skamil 67781.106Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67791.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67801.106Skamil 67811.106Skamil validate_status_stopped(status, sigval); 67821.106Skamil 67831.106Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 67841.106Skamil trackfork ? "|PTRACE_FORK" : "", 67851.106Skamil trackvfork ? "|PTRACE_VFORK" : "", 67861.106Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 67871.106Skamil event.pe_set_event = 0; 67881.106Skamil if (trackfork) 67891.106Skamil event.pe_set_event |= PTRACE_FORK; 67901.106Skamil if (trackvfork) 67911.106Skamil event.pe_set_event |= PTRACE_VFORK; 67921.106Skamil if (trackvforkdone) 67931.106Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 67941.106Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 67951.106Skamil 67961.106Skamil DPRINTF("Before resuming the child process where it left off and " 67971.106Skamil "without signal to be sent\n"); 67981.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 67991.106Skamil 68001.106Skamil#if defined(TWAIT_HAVE_PID) 68011.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 68021.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 68031.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 68041.106Skamil child); 68051.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 68061.106Skamil child); 68071.106Skamil 68081.106Skamil validate_status_stopped(status, SIGTRAP); 68091.106Skamil 68101.106Skamil SYSCALL_REQUIRE( 68111.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 68121.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 68131.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 68141.106Skamil PTRACE_FORK); 68151.106Skamil } 68161.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 68171.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 68181.106Skamil PTRACE_VFORK); 68191.106Skamil } 68201.106Skamil 68211.106Skamil child2 = state.pe_other_pid; 68221.106Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 68231.106Skamil 68241.106Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 68251.106Skamil "%d\n", TWAIT_FNAME, child2, child); 68261.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 68271.106Skamil child2); 68281.106Skamil 68291.106Skamil validate_status_stopped(status, SIGTRAP); 68301.106Skamil 68311.106Skamil SYSCALL_REQUIRE( 68321.106Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 68331.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 68341.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 68351.106Skamil PTRACE_FORK); 68361.106Skamil } 68371.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 68381.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 68391.106Skamil PTRACE_VFORK); 68401.106Skamil } 68411.106Skamil 68421.106Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 68431.106Skamil 68441.106Skamil DPRINTF("Before resuming the forkee process where it left off " 68451.106Skamil "and without signal to be sent\n"); 68461.106Skamil SYSCALL_REQUIRE( 68471.106Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 68481.106Skamil 68491.106Skamil DPRINTF("Before resuming the child process where it left off " 68501.106Skamil "and without signal to be sent\n"); 68511.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68521.106Skamil } 68531.106Skamil#endif 68541.106Skamil 68551.106Skamil if (trackvforkdone && (flags & CLONE_VFORK)) { 68561.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 68571.106Skamil child); 68581.106Skamil TWAIT_REQUIRE_SUCCESS( 68591.106Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 68601.106Skamil 68611.106Skamil validate_status_stopped(status, SIGTRAP); 68621.106Skamil 68631.106Skamil SYSCALL_REQUIRE( 68641.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 68651.106Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 68661.106Skamil 68671.106Skamil child2 = state.pe_other_pid; 68681.106Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 68691.106Skamil child2); 68701.106Skamil 68711.106Skamil DPRINTF("Before resuming the child process where it left off " 68721.106Skamil "and without signal to be sent\n"); 68731.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68741.106Skamil } 68751.106Skamil 68761.103Skamil#if defined(TWAIT_HAVE_PID) 68771.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 68781.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 68791.106Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 68801.106Skamil "\n", TWAIT_FNAME); 68811.106Skamil TWAIT_REQUIRE_SUCCESS( 68821.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 68831.106Skamil 68841.106Skamil validate_status_exited(status, exitval2); 68851.106Skamil 68861.106Skamil DPRINTF("Before calling %s() for the forkee - expected no " 68871.106Skamil "process\n", TWAIT_FNAME); 68881.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 68891.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 68901.106Skamil } 68911.106Skamil#endif 68921.106Skamil 68931.106Skamil DPRINTF("Before calling %s() for the child - expected stopped " 68941.106Skamil "SIGCHLD\n", TWAIT_FNAME); 68951.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68961.106Skamil 68971.106Skamil validate_status_stopped(status, SIGCHLD); 68981.106Skamil 68991.106Skamil DPRINTF("Before resuming the child process where it left off and " 69001.106Skamil "without signal to be sent\n"); 69011.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69021.106Skamil 69031.106Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 69041.106Skamil TWAIT_FNAME); 69051.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 69061.106Skamil 69071.106Skamil validate_status_exited(status, exitval); 69081.103Skamil 69091.106Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 69101.106Skamil TWAIT_FNAME); 69111.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 69121.106Skamil} 69131.103Skamil 69141.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone) \ 69151.106SkamilATF_TC(name); \ 69161.106SkamilATF_TC_HEAD(name, tc) \ 69171.106Skamil{ \ 69181.106Skamil atf_tc_set_md_var(tc, "descr", "Verify clone(%s) " \ 69191.106Skamil "called with 0%s%s%s in EVENT_MASK", \ 69201.106Skamil #flags, \ 69211.106Skamil tfork ? "|PTRACE_FORK" : "", \ 69221.106Skamil tvfork ? "|PTRACE_VFORK" : "", \ 69231.106Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 69241.106Skamil} \ 69251.106Skamil \ 69261.106SkamilATF_TC_BODY(name, tc) \ 69271.106Skamil{ \ 69281.106Skamil \ 69291.106Skamil clone_body(flags, tfork, tvfork, tvforkdone); \ 69301.103Skamil} 69311.103Skamil 69321.106SkamilCLONE_TEST(clone1, 0, false, false, false) 69331.106Skamil#if defined(TWAIT_HAVE_PID) 69341.106SkamilCLONE_TEST(clone2, 0, true, false, false) 69351.106SkamilCLONE_TEST(clone3, 0, false, true, false) 69361.106SkamilCLONE_TEST(clone4, 0, true, true, false) 69371.106Skamil#endif 69381.106SkamilCLONE_TEST(clone5, 0, false, false, true) 69391.106Skamil#if defined(TWAIT_HAVE_PID) 69401.106SkamilCLONE_TEST(clone6, 0, true, false, true) 69411.106SkamilCLONE_TEST(clone7, 0, false, true, true) 69421.106SkamilCLONE_TEST(clone8, 0, true, true, true) 69431.106Skamil#endif 69441.106Skamil 69451.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false) 69461.106Skamil#if defined(TWAIT_HAVE_PID) 69471.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false) 69481.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false) 69491.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false) 69501.106Skamil#endif 69511.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true) 69521.106Skamil#if defined(TWAIT_HAVE_PID) 69531.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true) 69541.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true) 69551.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true) 69561.106Skamil#endif 69571.106Skamil 69581.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false) 69591.106Skamil#if defined(TWAIT_HAVE_PID) 69601.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false) 69611.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false) 69621.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false) 69631.106Skamil#endif 69641.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true) 69651.106Skamil#if defined(TWAIT_HAVE_PID) 69661.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true) 69671.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true) 69681.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true) 69691.106Skamil#endif 69701.106Skamil 69711.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false) 69721.106Skamil#if defined(TWAIT_HAVE_PID) 69731.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false) 69741.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false) 69751.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false) 69761.106Skamil#endif 69771.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true) 69781.106Skamil#if defined(TWAIT_HAVE_PID) 69791.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true) 69801.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true) 69811.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true) 69821.106Skamil#endif 69831.106Skamil 69841.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false) 69851.106Skamil#if defined(TWAIT_HAVE_PID) 69861.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false) 69871.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false) 69881.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false) 69891.106Skamil#endif 69901.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true) 69911.106Skamil#if defined(TWAIT_HAVE_PID) 69921.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true) 69931.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true) 69941.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true) 69951.106Skamil#endif 69961.106Skamil 69971.110Skamil#if TEST_VFORK_ENABLED 69981.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false) 69991.106Skamil#if defined(TWAIT_HAVE_PID) 70001.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false) 70011.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false) 70021.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false) 70031.106Skamil#endif 70041.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true) 70051.106Skamil#if defined(TWAIT_HAVE_PID) 70061.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true) 70071.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true) 70081.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true) 70091.106Skamil#endif 70101.110Skamil#endif 70111.106Skamil 70121.106Skamil/// ---------------------------------------------------------------------------- 70131.106Skamil 70141.106Skamil#if defined(TWAIT_HAVE_PID) 70151.103Skamilstatic void 70161.106Skamilclone_body2(int flags, bool masked, bool ignored) 70171.103Skamil{ 70181.103Skamil const int exitval = 5; 70191.103Skamil const int exitval2 = 15; 70201.103Skamil const int sigval = SIGSTOP; 70211.103Skamil pid_t child, child2 = 0, wpid; 70221.103Skamil#if defined(TWAIT_HAVE_STATUS) 70231.103Skamil int status; 70241.103Skamil#endif 70251.103Skamil ptrace_state_t state; 70261.103Skamil const int slen = sizeof(state); 70271.103Skamil ptrace_event_t event; 70281.103Skamil const int elen = sizeof(event); 70291.103Skamil struct sigaction sa; 70301.103Skamil struct ptrace_siginfo info; 70311.103Skamil sigset_t intmask; 70321.103Skamil struct kinfo_proc2 kp; 70331.103Skamil size_t len = sizeof(kp); 70341.103Skamil 70351.103Skamil int name[6]; 70361.103Skamil const size_t namelen = __arraycount(name); 70371.103Skamil ki_sigset_t kp_sigmask; 70381.103Skamil ki_sigset_t kp_sigignore; 70391.103Skamil 70401.103Skamil const size_t stack_size = 1024 * 1024; 70411.103Skamil void *stack, *stack_base; 70421.103Skamil 70431.103Skamil stack = malloc(stack_size); 70441.103Skamil ATF_REQUIRE(stack != NULL); 70451.103Skamil 70461.103Skamil#ifdef __MACHINE_STACK_GROWS_UP 70471.103Skamil stack_base = stack; 70481.103Skamil#else 70491.103Skamil stack_base = (char *)stack + stack_size; 70501.103Skamil#endif 70511.103Skamil 70521.103Skamil SYSCALL_REQUIRE((child = fork()) != -1); 70531.103Skamil if (child == 0) { 70541.103Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 70551.103Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 70561.103Skamil 70571.103Skamil if (masked) { 70581.103Skamil sigemptyset(&intmask); 70591.103Skamil sigaddset(&intmask, SIGTRAP); 70601.103Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 70611.103Skamil } 70621.103Skamil 70631.103Skamil if (ignored) { 70641.103Skamil memset(&sa, 0, sizeof(sa)); 70651.103Skamil sa.sa_handler = SIG_IGN; 70661.103Skamil sigemptyset(&sa.sa_mask); 70671.103Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 70681.103Skamil } 70691.103Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 70701.103Skamil FORKEE_ASSERT(raise(sigval) == 0); 70711.103Skamil 70721.103Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 70731.103Skamil flags); 70741.103Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 70751.103Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 70761.103Skamil 70771.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 70781.103Skamil child2); 70791.103Skamil 70801.103Skamil // XXX WALLSIG? 70811.103Skamil FORKEE_REQUIRE_SUCCESS 70821.103Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 70831.103Skamil 70841.103Skamil forkee_status_exited(status, exitval2); 70851.103Skamil 70861.103Skamil DPRINTF("Before exiting of the child process\n"); 70871.103Skamil _exit(exitval); 70881.103Skamil } 70891.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 70901.103Skamil 70911.103Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 70921.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 70931.103Skamil 70941.103Skamil validate_status_stopped(status, sigval); 70951.103Skamil 70961.103Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 70971.103Skamil SYSCALL_REQUIRE( 70981.103Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 70991.103Skamil 71001.103Skamil DPRINTF("Before checking siginfo_t\n"); 71011.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 71021.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 71031.103Skamil 71041.103Skamil name[0] = CTL_KERN, 71051.103Skamil name[1] = KERN_PROC2, 71061.103Skamil name[2] = KERN_PROC_PID; 71071.103Skamil name[3] = child; 71081.103Skamil name[4] = sizeof(kp); 71091.103Skamil name[5] = 1; 71101.103Skamil 71111.103Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 71121.103Skamil 71131.103Skamil if (masked) 71141.103Skamil kp_sigmask = kp.p_sigmask; 71151.103Skamil 71161.103Skamil if (ignored) 71171.103Skamil kp_sigignore = kp.p_sigignore; 71181.103Skamil 71191.103Skamil DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in " 71201.103Skamil "EVENT_MASK for the child %d\n", child); 71211.103Skamil event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE; 71221.103Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 71231.103Skamil 71241.103Skamil DPRINTF("Before resuming the child process where it left off and " 71251.103Skamil "without signal to be sent\n"); 71261.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 71271.103Skamil 71281.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 71291.103Skamil child); 71301.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 71311.103Skamil child); 71321.103Skamil 71331.103Skamil validate_status_stopped(status, SIGTRAP); 71341.103Skamil 71351.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 71361.103Skamil 71371.103Skamil if (masked) { 71381.103Skamil DPRINTF("kp_sigmask=" 71391.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71401.103Skamil PRIx32 "\n", 71411.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 71421.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 71431.103Skamil 71441.103Skamil DPRINTF("kp.p_sigmask=" 71451.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71461.103Skamil PRIx32 "\n", 71471.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 71481.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 71491.103Skamil 71501.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 71511.103Skamil sizeof(kp_sigmask))); 71521.103Skamil } 71531.103Skamil 71541.103Skamil if (ignored) { 71551.103Skamil DPRINTF("kp_sigignore=" 71561.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71571.103Skamil PRIx32 "\n", 71581.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 71591.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 71601.103Skamil 71611.103Skamil DPRINTF("kp.p_sigignore=" 71621.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71631.103Skamil PRIx32 "\n", 71641.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 71651.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 71661.103Skamil 71671.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 71681.103Skamil sizeof(kp_sigignore))); 71691.103Skamil } 71701.103Skamil 71711.103Skamil SYSCALL_REQUIRE( 71721.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 71731.103Skamil DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event, 71741.103Skamil child2); 71751.103Skamil if (!(flags & CLONE_VFORK)) { 71761.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 71771.103Skamil PTRACE_FORK); 71781.103Skamil } else { 71791.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 71801.103Skamil PTRACE_VFORK); 71811.103Skamil } 71821.103Skamil 71831.103Skamil child2 = state.pe_other_pid; 71841.103Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 71851.103Skamil 71861.103Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 71871.103Skamil "%d\n", TWAIT_FNAME, child2, child); 71881.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 71891.103Skamil child2); 71901.103Skamil 71911.103Skamil validate_status_stopped(status, SIGTRAP); 71921.103Skamil 71931.103Skamil name[3] = child2; 71941.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 71951.103Skamil 71961.103Skamil if (masked) { 71971.103Skamil DPRINTF("kp_sigmask=" 71981.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71991.103Skamil PRIx32 "\n", 72001.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 72011.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 72021.103Skamil 72031.103Skamil DPRINTF("kp.p_sigmask=" 72041.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72051.103Skamil PRIx32 "\n", 72061.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 72071.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 72081.103Skamil 72091.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 72101.103Skamil sizeof(kp_sigmask))); 72111.103Skamil } 72121.103Skamil 72131.103Skamil if (ignored) { 72141.103Skamil DPRINTF("kp_sigignore=" 72151.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72161.103Skamil PRIx32 "\n", 72171.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 72181.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 72191.103Skamil 72201.103Skamil DPRINTF("kp.p_sigignore=" 72211.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72221.103Skamil PRIx32 "\n", 72231.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 72241.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 72251.103Skamil 72261.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 72271.103Skamil sizeof(kp_sigignore))); 72281.103Skamil } 72291.103Skamil 72301.103Skamil SYSCALL_REQUIRE( 72311.103Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 72321.103Skamil if (!(flags & CLONE_VFORK)) { 72331.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 72341.103Skamil PTRACE_FORK); 72351.103Skamil } else { 72361.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 72371.103Skamil PTRACE_VFORK); 72381.103Skamil } 72391.103Skamil 72401.103Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 72411.103Skamil 72421.103Skamil DPRINTF("Before resuming the forkee process where it left off " 72431.103Skamil "and without signal to be sent\n"); 72441.103Skamil SYSCALL_REQUIRE( 72451.103Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 72461.103Skamil 72471.103Skamil DPRINTF("Before resuming the child process where it left off " 72481.103Skamil "and without signal to be sent\n"); 72491.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 72501.103Skamil 72511.103Skamil if (flags & CLONE_VFORK) { 72521.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 72531.103Skamil child); 72541.103Skamil TWAIT_REQUIRE_SUCCESS( 72551.103Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 72561.103Skamil 72571.103Skamil validate_status_stopped(status, SIGTRAP); 72581.103Skamil 72591.103Skamil name[3] = child; 72601.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 72611.103Skamil 72621.103Skamil /* 72631.103Skamil * SIGCHLD is now pending in the signal queue and 72641.103Skamil * the kernel presents it to userland as a masked signal. 72651.103Skamil */ 72661.103Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 72671.103Skamil 72681.103Skamil if (masked) { 72691.103Skamil DPRINTF("kp_sigmask=" 72701.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72711.103Skamil PRIx32 "\n", 72721.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 72731.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 72741.103Skamil 72751.103Skamil DPRINTF("kp.p_sigmask=" 72761.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72771.103Skamil PRIx32 "\n", 72781.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 72791.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 72801.103Skamil 72811.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 72821.103Skamil sizeof(kp_sigmask))); 72831.103Skamil } 72841.103Skamil 72851.103Skamil if (ignored) { 72861.103Skamil DPRINTF("kp_sigignore=" 72871.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72881.103Skamil PRIx32 "\n", 72891.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 72901.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 72911.103Skamil 72921.103Skamil DPRINTF("kp.p_sigignore=" 72931.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72941.103Skamil PRIx32 "\n", 72951.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 72961.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 72971.103Skamil 72981.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 72991.103Skamil sizeof(kp_sigignore))); 73001.103Skamil } 73011.103Skamil 73021.103Skamil SYSCALL_REQUIRE( 73031.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 73041.103Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 73051.103Skamil 73061.103Skamil child2 = state.pe_other_pid; 73071.103Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 73081.103Skamil child2); 73091.103Skamil 73101.103Skamil DPRINTF("Before resuming the child process where it left off " 73111.103Skamil "and without signal to be sent\n"); 73121.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 73131.103Skamil } 73141.103Skamil 73151.103Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 73161.103Skamil "\n", TWAIT_FNAME); 73171.103Skamil TWAIT_REQUIRE_SUCCESS( 73181.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 73191.103Skamil 73201.103Skamil validate_status_exited(status, exitval2); 73211.103Skamil 73221.103Skamil DPRINTF("Before calling %s() for the forkee - expected no " 73231.103Skamil "process\n", TWAIT_FNAME); 73241.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 73251.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 73261.103Skamil 73271.103Skamil DPRINTF("Before calling %s() for the child - expected stopped " 73281.103Skamil "SIGCHLD\n", TWAIT_FNAME); 73291.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 73301.103Skamil 73311.103Skamil validate_status_stopped(status, SIGCHLD); 73321.103Skamil 73331.103Skamil DPRINTF("Before resuming the child process where it left off and " 73341.103Skamil "without signal to be sent\n"); 73351.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 73361.103Skamil 73371.103Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 73381.103Skamil TWAIT_FNAME); 73391.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 73401.103Skamil 73411.103Skamil validate_status_exited(status, exitval); 73421.103Skamil 73431.103Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 73441.103Skamil TWAIT_FNAME); 73451.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 73461.103Skamil} 73471.103Skamil 73481.106Skamil#define CLONE_TEST2(name,flags,masked,ignored) \ 73491.103SkamilATF_TC(name); \ 73501.103SkamilATF_TC_HEAD(name, tc) \ 73511.103Skamil{ \ 73521.103Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\ 73531.103Skamil " regardless of signal %s%s", \ 73541.103Skamil #flags, masked ? "masked" : "", ignored ? "ignored" : ""); \ 73551.103Skamil} \ 73561.103Skamil \ 73571.103SkamilATF_TC_BODY(name, tc) \ 73581.103Skamil{ \ 73591.103Skamil \ 73601.106Skamil clone_body2(flags, masked, ignored); \ 73611.103Skamil} 73621.103Skamil 73631.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false) 73641.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true) 73651.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false) 73661.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true) 73671.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false) 73681.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true) 73691.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false) 73701.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true) 73711.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX 73721.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true) // XXX 73731.110Skamil#if TEST_VFORK_ENABLED 73741.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false) 73751.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true) 73761.103Skamil#endif 73771.110Skamil#endif 73781.103Skamil 73791.103Skamil/// ---------------------------------------------------------------------------- 73801.103Skamil 73811.111Skamil#if TEST_VFORK_ENABLED 73821.107Skamil#if defined(TWAIT_HAVE_PID) 73831.107Skamilstatic void 73841.107Skamiltraceme_vfork_clone_body(int flags) 73851.107Skamil{ 73861.107Skamil const int exitval = 5; 73871.107Skamil const int exitval2 = 15; 73881.107Skamil pid_t child, child2 = 0, wpid; 73891.107Skamil#if defined(TWAIT_HAVE_STATUS) 73901.107Skamil int status; 73911.107Skamil#endif 73921.107Skamil 73931.107Skamil const size_t stack_size = 1024 * 1024; 73941.107Skamil void *stack, *stack_base; 73951.107Skamil 73961.107Skamil stack = malloc(stack_size); 73971.107Skamil ATF_REQUIRE(stack != NULL); 73981.107Skamil 73991.107Skamil#ifdef __MACHINE_STACK_GROWS_UP 74001.107Skamil stack_base = stack; 74011.107Skamil#else 74021.107Skamil stack_base = (char *)stack + stack_size; 74031.107Skamil#endif 74041.107Skamil 74051.107Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 74061.107Skamil if (child == 0) { 74071.107Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 74081.107Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 74091.107Skamil 74101.107Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 74111.107Skamil flags); 74121.107Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 74131.107Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 74141.107Skamil 74151.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 74161.107Skamil child2); 74171.107Skamil 74181.107Skamil // XXX WALLSIG? 74191.107Skamil FORKEE_REQUIRE_SUCCESS 74201.107Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 74211.107Skamil 74221.107Skamil forkee_status_exited(status, exitval2); 74231.107Skamil 74241.107Skamil DPRINTF("Before exiting of the child process\n"); 74251.107Skamil _exit(exitval); 74261.107Skamil } 74271.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 74281.107Skamil 74291.107Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 74301.107Skamil TWAIT_FNAME); 74311.107Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74321.107Skamil 74331.107Skamil validate_status_exited(status, exitval); 74341.107Skamil 74351.107Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 74361.107Skamil TWAIT_FNAME); 74371.107Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 74381.107Skamil} 74391.107Skamil 74401.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags) \ 74411.107SkamilATF_TC(name); \ 74421.107SkamilATF_TC_HEAD(name, tc) \ 74431.107Skamil{ \ 74441.107Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is " \ 74451.107Skamil "handled correctly with vfork(2)ed tracer", \ 74461.107Skamil #flags); \ 74471.107Skamil} \ 74481.107Skamil \ 74491.107SkamilATF_TC_BODY(name, tc) \ 74501.107Skamil{ \ 74511.107Skamil \ 74521.107Skamil traceme_vfork_clone_body(flags); \ 74531.107Skamil} 74541.107Skamil 74551.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0) 74561.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM) 74571.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS) 74581.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES) 74591.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND) // XXX 74601.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK) 74611.107Skamil#endif 74621.110Skamil#endif 74631.107Skamil 74641.107Skamil/// ---------------------------------------------------------------------------- 74651.107Skamil 74661.122Skamilstatic void 74671.122Skamiluser_va0_disable(int operation) 74681.122Skamil{ 74691.122Skamil pid_t child, wpid; 74701.122Skamil#if defined(TWAIT_HAVE_STATUS) 74711.122Skamil int status; 74721.122Skamil#endif 74731.122Skamil const int sigval = SIGSTOP; 74741.122Skamil int rv; 74751.122Skamil 74761.122Skamil struct ptrace_siginfo info; 74771.122Skamil 74781.122Skamil if (get_user_va0_disable() == 0) 74791.122Skamil atf_tc_skip("vm.user_va0_disable is set to 0"); 74801.122Skamil 74811.122Skamil memset(&info, 0, sizeof(info)); 74821.122Skamil 74831.122Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 74841.122Skamil SYSCALL_REQUIRE((child = fork()) != -1); 74851.122Skamil if (child == 0) { 74861.122Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 74871.122Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 74881.122Skamil 74891.122Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 74901.122Skamil FORKEE_ASSERT(raise(sigval) == 0); 74911.122Skamil 74921.122Skamil /* NOTREACHED */ 74931.122Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 74941.122Skamil __unreachable(); 74951.122Skamil } 74961.122Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 74971.122Skamil 74981.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 74991.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75001.122Skamil 75011.122Skamil validate_status_stopped(status, sigval); 75021.122Skamil 75031.122Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 75041.122Skamil "child\n"); 75051.122Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 75061.122Skamil sizeof(info)) != -1); 75071.122Skamil 75081.122Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 75091.122Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 75101.122Skamil "si_errno=%#x\n", 75111.122Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 75121.122Skamil info.psi_siginfo.si_errno); 75131.122Skamil 75141.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 75151.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 75161.122Skamil 75171.122Skamil DPRINTF("Before resuming the child process in PC=0x0 " 75181.122Skamil "and without signal to be sent\n"); 75191.122Skamil errno = 0; 75201.122Skamil rv = ptrace(operation, child, (void *)0, 0); 75211.122Skamil ATF_REQUIRE_EQ(errno, EINVAL); 75221.122Skamil ATF_REQUIRE_EQ(rv, -1); 75231.122Skamil 75241.122Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 75251.122Skamil 75261.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75271.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75281.122Skamil validate_status_signaled(status, SIGKILL, 0); 75291.122Skamil 75301.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75311.122Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 75321.122Skamil} 75331.122Skamil 75341.122Skamil#define USER_VA0_DISABLE(test, operation) \ 75351.122SkamilATF_TC(test); \ 75361.122SkamilATF_TC_HEAD(test, tc) \ 75371.122Skamil{ \ 75381.122Skamil atf_tc_set_md_var(tc, "descr", \ 75391.122Skamil "Verify behavior of " #operation " with PC set to 0x0"); \ 75401.122Skamil} \ 75411.122Skamil \ 75421.122SkamilATF_TC_BODY(test, tc) \ 75431.122Skamil{ \ 75441.122Skamil \ 75451.122Skamil user_va0_disable(operation); \ 75461.122Skamil} 75471.122Skamil 75481.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE) 75491.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL) 75501.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH) 75511.122Skamil 75521.122Skamil/// ---------------------------------------------------------------------------- 75531.122Skamil 75541.1Skamil#include "t_ptrace_amd64_wait.h" 75551.1Skamil#include "t_ptrace_i386_wait.h" 75561.1Skamil#include "t_ptrace_x86_wait.h" 75571.1Skamil 75581.1SkamilATF_TP_ADD_TCS(tp) 75591.1Skamil{ 75601.1Skamil setvbuf(stdout, NULL, _IONBF, 0); 75611.1Skamil setvbuf(stderr, NULL, _IONBF, 0); 75621.33Skamil 75631.36Skamil ATF_TP_ADD_TC(tp, traceme_raise1); 75641.33Skamil ATF_TP_ADD_TC(tp, traceme_raise2); 75651.33Skamil ATF_TP_ADD_TC(tp, traceme_raise3); 75661.33Skamil ATF_TP_ADD_TC(tp, traceme_raise4); 75671.33Skamil ATF_TP_ADD_TC(tp, traceme_raise5); 75681.85Skamil ATF_TP_ADD_TC(tp, traceme_raise6); 75691.85Skamil ATF_TP_ADD_TC(tp, traceme_raise7); 75701.85Skamil ATF_TP_ADD_TC(tp, traceme_raise8); 75711.85Skamil ATF_TP_ADD_TC(tp, traceme_raise9); 75721.85Skamil ATF_TP_ADD_TC(tp, traceme_raise10); 75731.33Skamil 75741.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1); 75751.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2); 75761.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3); 75771.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4); 75781.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5); 75791.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6); 75801.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7); 75811.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8); 75821.87Skamil 75831.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1); 75841.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2); 75851.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3); 75861.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4); 75871.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5); 75881.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6); 75891.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7); 75901.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8); 75911.86Skamil 75921.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_trap); 75931.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_segv); 75941.71Skamil ATF_TP_ADD_TC(tp, traceme_crash_ill); 75951.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_fpe); 75961.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_bus); 75971.59Skamil 75981.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap); 75991.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv); 76001.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill); 76011.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe); 76021.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus); 76031.88Skamil 76041.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap); 76051.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv); 76061.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill); 76071.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe); 76081.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus); 76091.88Skamil 76101.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1); 76111.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2); 76121.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3); 76131.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4); 76141.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5); 76151.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6); 76161.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7); 76171.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8); 76181.50Skamil 76191.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1); 76201.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2); 76211.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3); 76221.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4); 76231.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5); 76241.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6); 76251.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7); 76261.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8); 76271.50Skamil 76281.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1); 76291.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2); 76301.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3); 76311.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4); 76321.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5); 76331.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6); 76341.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7); 76351.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8); 76361.50Skamil 76371.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1); 76381.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2); 76391.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3); 76401.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4); 76411.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5); 76421.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6); 76431.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7); 76441.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8); 76451.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9); 76461.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10); 76471.1Skamil 76481.37Skamil ATF_TP_ADD_TC(tp, traceme_pid1_parent); 76491.37Skamil 76501.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise1); 76511.46Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise2); 76521.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise3); 76531.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise4); 76541.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise5); 76551.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise6); 76561.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise7); 76571.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise8); 76581.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise9); 76591.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise10); 76601.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise11); 76611.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise12); 76621.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise13); 76631.40Skamil 76641.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap); 76651.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv); 76661.71Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill); 76671.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe); 76681.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus); 76691.41Skamil 76701.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap); 76711.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv); 76721.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill); 76731.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe); 76741.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus); 76751.92Skamil 76761.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap); 76771.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv); 76781.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill); 76791.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe); 76801.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus); 76811.92Skamil 76821.43Skamil ATF_TP_ADD_TC(tp, traceme_vfork_exec); 76831.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec); 76841.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec); 76851.43Skamil 76861.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap); 76871.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv); 76881.71Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill); 76891.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe); 76901.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus); 76911.59Skamil 76921.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 76931.94Skamil unrelated_tracer_sees_signalmasked_crash_trap); 76941.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 76951.94Skamil unrelated_tracer_sees_signalmasked_crash_segv); 76961.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 76971.94Skamil unrelated_tracer_sees_signalmasked_crash_ill); 76981.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 76991.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe); 77001.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77011.94Skamil unrelated_tracer_sees_signalmasked_crash_bus); 77021.94Skamil 77031.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77041.94Skamil unrelated_tracer_sees_signalignored_crash_trap); 77051.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77061.94Skamil unrelated_tracer_sees_signalignored_crash_segv); 77071.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77081.94Skamil unrelated_tracer_sees_signalignored_crash_ill); 77091.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77101.94Skamil unrelated_tracer_sees_signalignored_crash_fpe); 77111.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77121.94Skamil unrelated_tracer_sees_signalignored_crash_bus); 77131.94Skamil 77141.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent); 77151.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates); 77161.61Skre ATF_TP_ADD_TC_HAVE_PID(tp, 77171.61Skre unrelated_tracer_sees_terminaton_before_the_parent); 77181.67Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process); 77191.51Skamil 77201.51Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_child); 77211.66Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child); 77221.51Skamil 77231.51Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_parent); 77241.65Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent); 77251.51Skamil 77261.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77271.51Skamil tracee_sees_its_original_parent_getppid); 77281.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77291.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2); 77301.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77311.51Skamil tracee_sees_its_original_parent_procfs_status); 77321.1Skamil 77331.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_empty); 77341.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_fork); 77351.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork); 77361.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done); 77371.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create); 77381.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit); 77391.1Skamil 77401.31Skamil ATF_TP_ADD_TC(tp, fork1); 77411.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork2); 77421.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork3); 77431.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork4); 77441.31Skamil ATF_TP_ADD_TC(tp, fork5); 77451.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork6); 77461.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork7); 77471.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork8); 77481.31Skamil 77491.109Skamil#if TEST_VFORK_ENABLED 77501.31Skamil ATF_TP_ADD_TC(tp, vfork1); 77511.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork2); 77521.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork3); 77531.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork4); 77541.31Skamil ATF_TP_ADD_TC(tp, vfork5); 77551.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork6); 77561.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork7); 77571.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork8); 77581.116Skamil#endif 77591.1Skamil 77601.124Skamil ATF_TP_ADD_TC(tp, posix_spawn1); 77611.124Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn2); 77621.124Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn3); 77631.124Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn4); 77641.124Skamil ATF_TP_ADD_TC(tp, posix_spawn5); 77651.124Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn6); 77661.124Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn7); 77671.124Skamil ATF_TP_ADD_TC_HAVE_PID(tp, posix_spawn8); 77681.124Skamil 77691.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_detach_forker); 77701.116Skamil#if TEST_VFORK_ENABLED 77711.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforker); 77721.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforkerdone); 77731.116Skamil#endif 77741.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_kill_forker); 77751.116Skamil#if TEST_VFORK_ENABLED 77761.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforker); 77771.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforkerdone); 77781.116Skamil#endif 77791.116Skamil 77801.116Skamil#if TEST_VFORK_ENABLED 77811.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_fork); 77821.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_vfork); 77831.109Skamil#endif 77841.108Skamil 77851.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8); 77861.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16); 77871.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32); 77881.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64); 77891.54Skamil 77901.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8); 77911.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16); 77921.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32); 77931.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64); 77941.54Skamil 77951.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8); 77961.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16); 77971.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32); 77981.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64); 77991.54Skamil 78001.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8); 78011.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16); 78021.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32); 78031.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64); 78041.54Skamil 78051.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d); 78061.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i); 78071.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d); 78081.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i); 78091.54Skamil 78101.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text); 78111.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text); 78121.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text); 78131.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text); 78141.54Skamil 78151.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text); 78161.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text); 78171.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text); 78181.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text); 78191.54Skamil 78201.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text); 78211.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text); 78221.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text); 78231.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text); 78241.54Skamil 78251.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text); 78261.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text); 78271.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text); 78281.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text); 78291.54Skamil 78301.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text); 78311.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text); 78321.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text); 78331.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text); 78341.1Skamil 78351.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv); 78361.1Skamil 78371.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i); 78381.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d); 78391.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i); 78401.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d); 78411.101Skamil 78421.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i); 78431.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d); 78441.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i); 78451.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d); 78461.101Skamil 78471.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv); 78481.101Skamil 78491.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i); 78501.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d); 78511.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i); 78521.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d); 78531.115Skamil 78541.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i); 78551.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d); 78561.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i); 78571.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d); 78581.115Skamil 78591.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1); 78601.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2); 78611.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3); 78621.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4); 78631.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5); 78641.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6); 78651.1Skamil 78661.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1); 78671.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2); 78681.1Skamil 78691.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step1); 78701.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step2); 78711.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step3); 78721.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step4); 78731.1Skamil 78741.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep1); 78751.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep2); 78761.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep3); 78771.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep4); 78781.2Skamil 78791.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked); 78801.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored); 78811.95Skamil 78821.1Skamil ATF_TP_ADD_TC(tp, kill1); 78831.1Skamil ATF_TP_ADD_TC(tp, kill2); 78841.75Skamil ATF_TP_ADD_TC(tp, kill3); 78851.1Skamil 78861.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0); 78871.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1); 78881.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2); 78891.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3); 78901.77Skamil 78911.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0); 78921.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1); 78931.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2); 78941.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3); 78951.1Skamil 78961.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_unmodified); 78971.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_faked); 78981.79Skamil 78991.82Skamil ATF_TP_ADD_TC(tp, traceme_exec); 79001.97Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_exec); 79011.97Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_exec); 79021.1Skamil 79031.119Skamil ATF_TP_ADD_TC(tp, trace_thread_nolwpevents); 79041.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpexit); 79051.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate); 79061.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit); 79071.1Skamil 79081.84Skamil ATF_TP_ADD_TC(tp, signal_mask_unrelated); 79091.84Skamil 79101.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked); 79111.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored); 79121.109Skamil#if TEST_VFORK_ENABLED 79131.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked); 79141.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored); 79151.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked); 79161.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored); 79171.109Skamil#endif 79181.99Skamil 79191.1Skamil ATF_TP_ADD_TC(tp, signal9); 79201.1Skamil ATF_TP_ADD_TC(tp, signal10); 79211.1Skamil 79221.1Skamil ATF_TP_ADD_TC(tp, suspend1); 79231.1Skamil ATF_TP_ADD_TC(tp, suspend2); 79241.1Skamil 79251.1Skamil ATF_TP_ADD_TC(tp, resume1); 79261.1Skamil 79271.1Skamil ATF_TP_ADD_TC(tp, syscall1); 79281.1Skamil 79291.1Skamil ATF_TP_ADD_TC(tp, syscallemu1); 79301.1Skamil 79311.106Skamil ATF_TP_ADD_TC(tp, clone1); 79321.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone2); 79331.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone3); 79341.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone4); 79351.106Skamil ATF_TP_ADD_TC(tp, clone5); 79361.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone6); 79371.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone7); 79381.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone8); 79391.106Skamil 79401.106Skamil ATF_TP_ADD_TC(tp, clone_vm1); 79411.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2); 79421.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3); 79431.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4); 79441.106Skamil ATF_TP_ADD_TC(tp, clone_vm5); 79451.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6); 79461.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7); 79471.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8); 79481.106Skamil 79491.106Skamil ATF_TP_ADD_TC(tp, clone_fs1); 79501.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2); 79511.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3); 79521.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4); 79531.106Skamil ATF_TP_ADD_TC(tp, clone_fs5); 79541.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6); 79551.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7); 79561.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8); 79571.106Skamil 79581.106Skamil ATF_TP_ADD_TC(tp, clone_files1); 79591.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2); 79601.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3); 79611.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4); 79621.106Skamil ATF_TP_ADD_TC(tp, clone_files5); 79631.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6); 79641.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7); 79651.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8); 79661.106Skamil 79671.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand1); // XXX 79681.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX 79691.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX 79701.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX 79711.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand5); // XXX 79721.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX 79731.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX 79741.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX 79751.106Skamil 79761.109Skamil#if TEST_VFORK_ENABLED 79771.106Skamil ATF_TP_ADD_TC(tp, clone_vfork1); 79781.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2); 79791.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3); 79801.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4); 79811.106Skamil ATF_TP_ADD_TC(tp, clone_vfork5); 79821.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6); 79831.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7); 79841.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8); 79851.109Skamil#endif 79861.106Skamil 79871.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored); 79881.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked); 79891.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored); 79901.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked); 79911.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored); 79921.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked); 79931.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored); 79941.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked); 79951.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX 79961.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX 79971.109Skamil#if TEST_VFORK_ENABLED 79981.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored); 79991.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked); 80001.109Skamil#endif 80011.103Skamil 80021.109Skamil#if TEST_VFORK_ENABLED 80031.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone); 80041.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm); 80051.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs); 80061.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files); 80071.107Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX 80081.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork); 80091.109Skamil#endif 80101.107Skamil 80111.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue); 80121.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall); 80131.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach); 80141.122Skamil 80151.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64(); 80161.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_I386(); 80171.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_X86(); 80181.1Skamil 80191.1Skamil return atf_no_error(); 80201.1Skamil} 8021