t_ptrace_wait.c revision 1.123
11.123Skamil/* $NetBSD: t_ptrace_wait.c,v 1.123 2019/06/10 21:18:04 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.123 2019/06/10 21:18:04 kamil Exp $"); 311.1Skamil 321.1Skamil#include <sys/param.h> 331.1Skamil#include <sys/types.h> 341.39Skamil#include <sys/mman.h> 351.1Skamil#include <sys/ptrace.h> 361.1Skamil#include <sys/resource.h> 371.1Skamil#include <sys/stat.h> 381.1Skamil#include <sys/syscall.h> 391.1Skamil#include <sys/sysctl.h> 401.1Skamil#include <sys/wait.h> 411.1Skamil#include <machine/reg.h> 421.1Skamil#include <elf.h> 431.1Skamil#include <err.h> 441.1Skamil#include <errno.h> 451.1Skamil#include <lwp.h> 461.77Skamil#include <pthread.h> 471.1Skamil#include <sched.h> 481.1Skamil#include <signal.h> 491.1Skamil#include <stdint.h> 501.1Skamil#include <stdio.h> 511.1Skamil#include <stdlib.h> 521.1Skamil#include <strings.h> 531.26Skamil#include <time.h> 541.1Skamil#include <unistd.h> 551.1Skamil 561.114Skamil#include <fenv.h> 571.114Skamil#if (__arm__ && !__SOFTFP__) || __aarch64__ 581.114Skamil#include <ieeefp.h> /* only need for ARM Cortex/Neon hack */ 591.114Skamil#endif 601.114Skamil 611.121Smgorny#if defined(__i386__) || defined(__x86_64__) 621.121Smgorny#include <cpuid.h> 631.121Smgorny#include <x86/cpu_extended_state.h> 641.121Smgorny#endif 651.121Smgorny 661.1Skamil#include <atf-c.h> 671.1Skamil 681.1Skamil#include "h_macros.h" 691.1Skamil 701.1Skamil#include "t_ptrace_wait.h" 711.1Skamil#include "msg.h" 721.1Skamil 731.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \ 741.61Skre SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \ 751.61Skre sizeof(msg)) == 0) 761.1Skamil 771.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \ 781.61Skre FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \ 791.61Skre sizeof(msg)) == 0) 801.1Skamil 811.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \ 821.61Skre FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \ 831.61Skre sizeof(msg)) == 0) 841.1Skamil 851.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \ 861.61Skre SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \ 871.61Skre sizeof(msg)) == 0) 881.13Schristos 891.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \ 901.13Schristos strerror(errno)) 911.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \ 921.18Schristos "%d(%s) != %d", res, strerror(res), exp) 931.13Schristos 941.13Schristosstatic int debug = 0; 951.13Schristos 961.13Schristos#define DPRINTF(a, ...) do \ 971.123Skamil if (debug) \ 981.123Skamil printf("%s() %s:%d " a, __func__, __FILE__, __LINE__, ##__VA_ARGS__); \ 991.13Schristos while (/*CONSTCOND*/0) 1001.1Skamil 1011.110Skamil#ifndef TEST_VFORK_ENABLED 1021.109Skamil#define TEST_VFORK_ENABLED 0 1031.110Skamil#endif 1041.109Skamil 1051.34Skamil/// ---------------------------------------------------------------------------- 1061.34Skamil 1071.33Skamilstatic void 1081.33Skamiltraceme_raise(int sigval) 1091.1Skamil{ 1101.1Skamil const int exitval = 5; 1111.1Skamil pid_t child, wpid; 1121.1Skamil#if defined(TWAIT_HAVE_STATUS) 1131.1Skamil int status; 1141.1Skamil#endif 1151.1Skamil 1161.45Skamil struct ptrace_siginfo info; 1171.45Skamil memset(&info, 0, sizeof(info)); 1181.45Skamil 1191.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 1201.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 1211.1Skamil if (child == 0) { 1221.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1231.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1241.1Skamil 1251.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1261.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 1271.1Skamil 1281.36Skamil switch (sigval) { 1291.36Skamil case SIGKILL: 1301.36Skamil /* NOTREACHED */ 1311.36Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 1321.70Smrg __unreachable(); 1331.36Skamil default: 1341.36Skamil DPRINTF("Before exiting of the child process\n"); 1351.36Skamil _exit(exitval); 1361.36Skamil } 1371.1Skamil } 1381.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1391.1Skamil 1401.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1411.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1421.1Skamil 1431.36Skamil switch (sigval) { 1441.36Skamil case SIGKILL: 1451.36Skamil validate_status_signaled(status, sigval, 0); 1461.36Skamil break; 1471.36Skamil default: 1481.36Skamil validate_status_stopped(status, sigval); 1491.1Skamil 1501.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 1511.61Skre "child\n"); 1521.45Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 1531.61Skre sizeof(info)) != -1); 1541.45Skamil 1551.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1561.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 1571.61Skre "si_errno=%#x\n", 1581.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1591.61Skre info.psi_siginfo.si_errno); 1601.45Skamil 1611.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 1621.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 1631.45Skamil 1641.36Skamil DPRINTF("Before resuming the child process where it left off " 1651.36Skamil "and without signal to be sent\n"); 1661.36Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1671.1Skamil 1681.36Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1691.36Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 1701.61Skre child); 1711.36Skamil break; 1721.36Skamil } 1731.1Skamil 1741.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1751.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 1761.1Skamil} 1771.1Skamil 1781.61Skre#define TRACEME_RAISE(test, sig) \ 1791.61SkreATF_TC(test); \ 1801.61SkreATF_TC_HEAD(test, tc) \ 1811.61Skre{ \ 1821.61Skre atf_tc_set_md_var(tc, "descr", \ 1831.61Skre "Verify " #sig " followed by _exit(2) in a child"); \ 1841.61Skre} \ 1851.61Skre \ 1861.61SkreATF_TC_BODY(test, tc) \ 1871.61Skre{ \ 1881.61Skre \ 1891.61Skre traceme_raise(sig); \ 1901.33Skamil} 1911.33Skamil 1921.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */ 1931.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */ 1941.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */ 1951.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP) /* hangup */ 1961.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */ 1971.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */ 1981.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */ 1991.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */ 2001.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */ 2011.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */ 2021.33Skamil 2031.34Skamil/// ---------------------------------------------------------------------------- 2041.1Skamil 2051.1Skamilstatic void 2061.87Skamiltraceme_raisesignal_ignored(int sigignored) 2071.87Skamil{ 2081.87Skamil const int exitval = 5; 2091.87Skamil const int sigval = SIGSTOP; 2101.87Skamil pid_t child, wpid; 2111.87Skamil struct sigaction sa; 2121.87Skamil#if defined(TWAIT_HAVE_STATUS) 2131.87Skamil int status; 2141.87Skamil#endif 2151.87Skamil struct ptrace_siginfo info; 2161.87Skamil 2171.87Skamil memset(&info, 0, sizeof(info)); 2181.87Skamil 2191.87Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 2201.87Skamil SYSCALL_REQUIRE((child = fork()) != -1); 2211.87Skamil if (child == 0) { 2221.87Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2231.87Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2241.87Skamil 2251.87Skamil memset(&sa, 0, sizeof(sa)); 2261.87Skamil sa.sa_handler = SIG_IGN; 2271.87Skamil sigemptyset(&sa.sa_mask); 2281.87Skamil FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1); 2291.87Skamil 2301.87Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 2311.87Skamil FORKEE_ASSERT(raise(sigval) == 0); 2321.87Skamil 2331.87Skamil DPRINTF("Before raising %s from child\n", 2341.87Skamil strsignal(sigignored)); 2351.87Skamil FORKEE_ASSERT(raise(sigignored) == 0); 2361.87Skamil 2371.87Skamil DPRINTF("Before exiting of the child process\n"); 2381.87Skamil _exit(exitval); 2391.87Skamil } 2401.87Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2411.87Skamil 2421.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2431.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2441.87Skamil 2451.87Skamil validate_status_stopped(status, sigval); 2461.87Skamil 2471.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2481.87Skamil SYSCALL_REQUIRE( 2491.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2501.87Skamil 2511.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2521.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2531.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2541.87Skamil info.psi_siginfo.si_errno); 2551.87Skamil 2561.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 2571.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2581.87Skamil 2591.87Skamil DPRINTF("Before resuming the child process where it left off and " 2601.87Skamil "without signal to be sent\n"); 2611.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2621.87Skamil 2631.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2641.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2651.87Skamil 2661.87Skamil validate_status_stopped(status, sigignored); 2671.87Skamil 2681.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2691.87Skamil SYSCALL_REQUIRE( 2701.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2711.87Skamil 2721.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2731.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2741.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2751.87Skamil info.psi_siginfo.si_errno); 2761.87Skamil 2771.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored); 2781.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2791.87Skamil 2801.87Skamil DPRINTF("Before resuming the child process where it left off and " 2811.87Skamil "without signal to be sent\n"); 2821.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2831.87Skamil 2841.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2851.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2861.87Skamil 2871.87Skamil validate_status_exited(status, exitval); 2881.87Skamil 2891.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2901.87Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 2911.87Skamil} 2921.87Skamil 2931.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig) \ 2941.87SkamilATF_TC(test); \ 2951.87SkamilATF_TC_HEAD(test, tc) \ 2961.87Skamil{ \ 2971.87Skamil atf_tc_set_md_var(tc, "descr", \ 2981.87Skamil "Verify that ignoring (with SIG_IGN) " #sig " in tracee " \ 2991.87Skamil "does not stop tracer from catching this raised signal"); \ 3001.87Skamil} \ 3011.87Skamil \ 3021.87SkamilATF_TC_BODY(test, tc) \ 3031.87Skamil{ \ 3041.87Skamil \ 3051.87Skamil traceme_raisesignal_ignored(sig); \ 3061.87Skamil} 3071.87Skamil 3081.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 3091.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */ 3101.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP) /* hangup */ 3111.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */ 3121.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */ 3131.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */ 3141.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */ 3151.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */ 3161.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */ 3171.87Skamil 3181.87Skamil/// ---------------------------------------------------------------------------- 3191.87Skamil 3201.87Skamilstatic void 3211.86Skamiltraceme_raisesignal_masked(int sigmasked) 3221.86Skamil{ 3231.86Skamil const int exitval = 5; 3241.86Skamil const int sigval = SIGSTOP; 3251.86Skamil pid_t child, wpid; 3261.86Skamil#if defined(TWAIT_HAVE_STATUS) 3271.86Skamil int status; 3281.86Skamil#endif 3291.86Skamil sigset_t intmask; 3301.86Skamil struct ptrace_siginfo info; 3311.86Skamil 3321.86Skamil memset(&info, 0, sizeof(info)); 3331.86Skamil 3341.86Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 3351.86Skamil SYSCALL_REQUIRE((child = fork()) != -1); 3361.86Skamil if (child == 0) { 3371.86Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 3381.86Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 3391.86Skamil 3401.86Skamil sigemptyset(&intmask); 3411.86Skamil sigaddset(&intmask, sigmasked); 3421.86Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 3431.86Skamil 3441.86Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 3451.86Skamil FORKEE_ASSERT(raise(sigval) == 0); 3461.86Skamil 3471.86Skamil DPRINTF("Before raising %s breakpoint from child\n", 3481.86Skamil strsignal(sigmasked)); 3491.86Skamil FORKEE_ASSERT(raise(sigmasked) == 0); 3501.86Skamil 3511.86Skamil DPRINTF("Before exiting of the child process\n"); 3521.86Skamil _exit(exitval); 3531.86Skamil } 3541.86Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 3551.86Skamil 3561.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3571.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3581.86Skamil 3591.86Skamil validate_status_stopped(status, sigval); 3601.86Skamil 3611.86Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 3621.86Skamil SYSCALL_REQUIRE( 3631.86Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 3641.86Skamil 3651.86Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 3661.86Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 3671.86Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 3681.86Skamil info.psi_siginfo.si_errno); 3691.86Skamil 3701.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 3711.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 3721.86Skamil 3731.86Skamil DPRINTF("Before resuming the child process where it left off and " 3741.86Skamil "without signal to be sent\n"); 3751.86Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 3761.86Skamil 3771.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3781.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3791.86Skamil 3801.86Skamil validate_status_exited(status, exitval); 3811.86Skamil 3821.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3831.86Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 3841.86Skamil} 3851.86Skamil 3861.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig) \ 3871.86SkamilATF_TC(test); \ 3881.86SkamilATF_TC_HEAD(test, tc) \ 3891.86Skamil{ \ 3901.86Skamil atf_tc_set_md_var(tc, "descr", \ 3911.86Skamil "Verify that masking (with SIG_BLOCK) " #sig " in tracee " \ 3921.86Skamil "stops tracer from catching this raised signal"); \ 3931.86Skamil} \ 3941.86Skamil \ 3951.86SkamilATF_TC_BODY(test, tc) \ 3961.86Skamil{ \ 3971.86Skamil \ 3981.86Skamil traceme_raisesignal_masked(sig); \ 3991.86Skamil} 4001.86Skamil 4011.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 4021.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */ 4031.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP) /* hangup */ 4041.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */ 4051.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */ 4061.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */ 4071.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */ 4081.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */ 4091.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */ 4101.86Skamil 4111.86Skamil/// ---------------------------------------------------------------------------- 4121.86Skamil 4131.86Skamilstatic void 4141.59Skamiltraceme_crash(int sig) 4151.59Skamil{ 4161.59Skamil pid_t child, wpid; 4171.59Skamil#if defined(TWAIT_HAVE_STATUS) 4181.59Skamil int status; 4191.59Skamil#endif 4201.59Skamil struct ptrace_siginfo info; 4211.61Skre 4221.71Skamil#ifndef PTRACE_ILLEGAL_ASM 4231.71Skamil if (sig == SIGILL) 4241.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 4251.71Skamil#endif 4261.71Skamil 4271.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 4281.114Skamil atf_tc_skip("FP exceptions are not supported"); 4291.114Skamil 4301.59Skamil memset(&info, 0, sizeof(info)); 4311.59Skamil 4321.59Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 4331.59Skamil SYSCALL_REQUIRE((child = fork()) != -1); 4341.59Skamil if (child == 0) { 4351.59Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 4361.59Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 4371.59Skamil 4381.59Skamil DPRINTF("Before executing a trap\n"); 4391.59Skamil switch (sig) { 4401.59Skamil case SIGTRAP: 4411.59Skamil trigger_trap(); 4421.59Skamil break; 4431.59Skamil case SIGSEGV: 4441.59Skamil trigger_segv(); 4451.59Skamil break; 4461.59Skamil case SIGILL: 4471.59Skamil trigger_ill(); 4481.59Skamil break; 4491.59Skamil case SIGFPE: 4501.59Skamil trigger_fpe(); 4511.59Skamil break; 4521.59Skamil case SIGBUS: 4531.59Skamil trigger_bus(); 4541.59Skamil break; 4551.59Skamil default: 4561.59Skamil /* NOTREACHED */ 4571.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4581.59Skamil } 4591.59Skamil 4601.59Skamil /* NOTREACHED */ 4611.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4621.59Skamil } 4631.59Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 4641.59Skamil 4651.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4661.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4671.59Skamil 4681.59Skamil validate_status_stopped(status, sig); 4691.59Skamil 4701.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 4711.61Skre SYSCALL_REQUIRE( 4721.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 4731.59Skamil 4741.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 4751.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 4761.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 4771.61Skre info.psi_siginfo.si_errno); 4781.59Skamil 4791.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 4801.59Skamil switch (sig) { 4811.59Skamil case SIGTRAP: 4821.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 4831.59Skamil break; 4841.59Skamil case SIGSEGV: 4851.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 4861.59Skamil break; 4871.71Skamil case SIGILL: 4881.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 4891.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 4901.71Skamil break; 4911.59Skamil case SIGFPE: 4921.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 4931.59Skamil break; 4941.59Skamil case SIGBUS: 4951.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 4961.59Skamil break; 4971.59Skamil } 4981.59Skamil 4991.59Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 5001.59Skamil 5011.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5021.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 5031.59Skamil 5041.59Skamil validate_status_signaled(status, SIGKILL, 0); 5051.59Skamil 5061.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5071.59Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 5081.59Skamil} 5091.59Skamil 5101.61Skre#define TRACEME_CRASH(test, sig) \ 5111.61SkreATF_TC(test); \ 5121.61SkreATF_TC_HEAD(test, tc) \ 5131.61Skre{ \ 5141.61Skre atf_tc_set_md_var(tc, "descr", \ 5151.61Skre "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \ 5161.61Skre} \ 5171.61Skre \ 5181.61SkreATF_TC_BODY(test, tc) \ 5191.61Skre{ \ 5201.61Skre \ 5211.61Skre traceme_crash(sig); \ 5221.59Skamil} 5231.59Skamil 5241.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP) 5251.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV) 5261.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL) 5271.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE) 5281.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS) 5291.59Skamil 5301.59Skamil/// ---------------------------------------------------------------------------- 5311.59Skamil 5321.59Skamilstatic void 5331.88Skamiltraceme_signalmasked_crash(int sig) 5341.88Skamil{ 5351.89Skamil const int sigval = SIGSTOP; 5361.88Skamil pid_t child, wpid; 5371.88Skamil#if defined(TWAIT_HAVE_STATUS) 5381.88Skamil int status; 5391.88Skamil#endif 5401.88Skamil struct ptrace_siginfo info; 5411.88Skamil sigset_t intmask; 5421.89Skamil struct kinfo_proc2 kp; 5431.89Skamil size_t len = sizeof(kp); 5441.89Skamil 5451.89Skamil int name[6]; 5461.89Skamil const size_t namelen = __arraycount(name); 5471.89Skamil ki_sigset_t kp_sigmask; 5481.88Skamil 5491.88Skamil#ifndef PTRACE_ILLEGAL_ASM 5501.88Skamil if (sig == SIGILL) 5511.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 5521.88Skamil#endif 5531.88Skamil 5541.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 5551.114Skamil atf_tc_skip("FP exceptions are not supported"); 5561.114Skamil 5571.88Skamil memset(&info, 0, sizeof(info)); 5581.88Skamil 5591.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 5601.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 5611.88Skamil if (child == 0) { 5621.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 5631.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 5641.88Skamil 5651.88Skamil sigemptyset(&intmask); 5661.88Skamil sigaddset(&intmask, sig); 5671.88Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 5681.88Skamil 5691.89Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 5701.89Skamil FORKEE_ASSERT(raise(sigval) == 0); 5711.89Skamil 5721.88Skamil DPRINTF("Before executing a trap\n"); 5731.88Skamil switch (sig) { 5741.88Skamil case SIGTRAP: 5751.88Skamil trigger_trap(); 5761.88Skamil break; 5771.88Skamil case SIGSEGV: 5781.88Skamil trigger_segv(); 5791.88Skamil break; 5801.88Skamil case SIGILL: 5811.88Skamil trigger_ill(); 5821.88Skamil break; 5831.88Skamil case SIGFPE: 5841.88Skamil trigger_fpe(); 5851.88Skamil break; 5861.88Skamil case SIGBUS: 5871.88Skamil trigger_bus(); 5881.88Skamil break; 5891.88Skamil default: 5901.88Skamil /* NOTREACHED */ 5911.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 5921.88Skamil } 5931.88Skamil 5941.88Skamil /* NOTREACHED */ 5951.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 5961.88Skamil } 5971.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 5981.88Skamil 5991.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6001.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6011.88Skamil 6021.89Skamil validate_status_stopped(status, sigval); 6031.89Skamil 6041.89Skamil name[0] = CTL_KERN, 6051.89Skamil name[1] = KERN_PROC2, 6061.89Skamil name[2] = KERN_PROC_PID; 6071.89Skamil name[3] = child; 6081.89Skamil name[4] = sizeof(kp); 6091.89Skamil name[5] = 1; 6101.89Skamil 6111.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6121.89Skamil 6131.89Skamil kp_sigmask = kp.p_sigmask; 6141.89Skamil 6151.89Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 6161.89Skamil SYSCALL_REQUIRE( 6171.89Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6181.89Skamil 6191.89Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6201.89Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6211.89Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6221.89Skamil info.psi_siginfo.si_errno); 6231.89Skamil 6241.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 6251.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 6261.89Skamil 6271.89Skamil DPRINTF("Before resuming the child process where it left off and " 6281.89Skamil "without signal to be sent\n"); 6291.89Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 6301.89Skamil 6311.89Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6321.89Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6331.89Skamil 6341.88Skamil validate_status_stopped(status, sig); 6351.88Skamil 6361.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 6371.88Skamil SYSCALL_REQUIRE( 6381.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6391.88Skamil 6401.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6411.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6421.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6431.88Skamil info.psi_siginfo.si_errno); 6441.88Skamil 6451.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6461.89Skamil 6471.89Skamil DPRINTF("kp_sigmask=" 6481.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6491.89Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2], 6501.89Skamil kp_sigmask.__bits[3]); 6511.89Skamil 6521.89Skamil DPRINTF("kp.p_sigmask=" 6531.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6541.89Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 6551.89Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 6561.89Skamil 6571.89Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask))); 6581.89Skamil 6591.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 6601.88Skamil switch (sig) { 6611.88Skamil case SIGTRAP: 6621.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 6631.88Skamil break; 6641.88Skamil case SIGSEGV: 6651.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 6661.88Skamil break; 6671.88Skamil case SIGILL: 6681.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 6691.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 6701.88Skamil break; 6711.88Skamil case SIGFPE: 6721.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 6731.88Skamil break; 6741.88Skamil case SIGBUS: 6751.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 6761.88Skamil break; 6771.88Skamil } 6781.88Skamil 6791.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 6801.88Skamil 6811.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6821.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6831.88Skamil 6841.88Skamil validate_status_signaled(status, SIGKILL, 0); 6851.88Skamil 6861.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6871.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 6881.88Skamil} 6891.88Skamil 6901.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig) \ 6911.88SkamilATF_TC(test); \ 6921.88SkamilATF_TC_HEAD(test, tc) \ 6931.88Skamil{ \ 6941.88Skamil atf_tc_set_md_var(tc, "descr", \ 6951.88Skamil "Verify masked crash signal " #sig " in a child after " \ 6961.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 6971.88Skamil} \ 6981.88Skamil \ 6991.88SkamilATF_TC_BODY(test, tc) \ 7001.88Skamil{ \ 7011.88Skamil \ 7021.88Skamil traceme_signalmasked_crash(sig); \ 7031.88Skamil} 7041.88Skamil 7051.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP) 7061.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV) 7071.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL) 7081.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE) 7091.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS) 7101.88Skamil 7111.88Skamil/// ---------------------------------------------------------------------------- 7121.88Skamil 7131.88Skamilstatic void 7141.88Skamiltraceme_signalignored_crash(int sig) 7151.88Skamil{ 7161.90Skamil const int sigval = SIGSTOP; 7171.88Skamil pid_t child, wpid; 7181.88Skamil#if defined(TWAIT_HAVE_STATUS) 7191.88Skamil int status; 7201.88Skamil#endif 7211.88Skamil struct sigaction sa; 7221.88Skamil struct ptrace_siginfo info; 7231.90Skamil struct kinfo_proc2 kp; 7241.90Skamil size_t len = sizeof(kp); 7251.90Skamil 7261.90Skamil int name[6]; 7271.90Skamil const size_t namelen = __arraycount(name); 7281.90Skamil ki_sigset_t kp_sigignore; 7291.88Skamil 7301.88Skamil#ifndef PTRACE_ILLEGAL_ASM 7311.88Skamil if (sig == SIGILL) 7321.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 7331.88Skamil#endif 7341.88Skamil 7351.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 7361.114Skamil atf_tc_skip("FP exceptions are not supported"); 7371.114Skamil 7381.88Skamil memset(&info, 0, sizeof(info)); 7391.88Skamil 7401.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 7411.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 7421.88Skamil if (child == 0) { 7431.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 7441.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 7451.88Skamil 7461.88Skamil memset(&sa, 0, sizeof(sa)); 7471.88Skamil sa.sa_handler = SIG_IGN; 7481.88Skamil sigemptyset(&sa.sa_mask); 7491.88Skamil 7501.88Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 7511.88Skamil 7521.90Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 7531.90Skamil FORKEE_ASSERT(raise(sigval) == 0); 7541.90Skamil 7551.88Skamil DPRINTF("Before executing a trap\n"); 7561.88Skamil switch (sig) { 7571.88Skamil case SIGTRAP: 7581.88Skamil trigger_trap(); 7591.88Skamil break; 7601.88Skamil case SIGSEGV: 7611.88Skamil trigger_segv(); 7621.88Skamil break; 7631.88Skamil case SIGILL: 7641.88Skamil trigger_ill(); 7651.88Skamil break; 7661.88Skamil case SIGFPE: 7671.88Skamil trigger_fpe(); 7681.88Skamil break; 7691.88Skamil case SIGBUS: 7701.88Skamil trigger_bus(); 7711.88Skamil break; 7721.88Skamil default: 7731.88Skamil /* NOTREACHED */ 7741.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7751.88Skamil } 7761.88Skamil 7771.88Skamil /* NOTREACHED */ 7781.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7791.88Skamil } 7801.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 7811.88Skamil 7821.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7831.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 7841.88Skamil 7851.90Skamil validate_status_stopped(status, sigval); 7861.90Skamil 7871.90Skamil name[0] = CTL_KERN, 7881.90Skamil name[1] = KERN_PROC2, 7891.90Skamil name[2] = KERN_PROC_PID; 7901.90Skamil name[3] = child; 7911.90Skamil name[4] = sizeof(kp); 7921.90Skamil name[5] = 1; 7931.90Skamil 7941.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 7951.90Skamil 7961.90Skamil kp_sigignore = kp.p_sigignore; 7971.90Skamil 7981.90Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 7991.90Skamil SYSCALL_REQUIRE( 8001.90Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8011.90Skamil 8021.90Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8031.90Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8041.90Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8051.90Skamil info.psi_siginfo.si_errno); 8061.90Skamil 8071.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 8081.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 8091.90Skamil 8101.90Skamil DPRINTF("Before resuming the child process where it left off and " 8111.90Skamil "without signal to be sent\n"); 8121.90Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 8131.90Skamil 8141.90Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8151.90Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8161.90Skamil 8171.88Skamil validate_status_stopped(status, sig); 8181.88Skamil 8191.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 8201.88Skamil SYSCALL_REQUIRE( 8211.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8221.88Skamil 8231.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8241.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8251.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8261.88Skamil info.psi_siginfo.si_errno); 8271.88Skamil 8281.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8291.90Skamil 8301.90Skamil DPRINTF("kp_sigignore=" 8311.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8321.90Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 8331.90Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 8341.90Skamil 8351.90Skamil DPRINTF("kp.p_sigignore=" 8361.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8371.90Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 8381.90Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 8391.90Skamil 8401.90Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore))); 8411.90Skamil 8421.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 8431.88Skamil switch (sig) { 8441.88Skamil case SIGTRAP: 8451.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 8461.88Skamil break; 8471.88Skamil case SIGSEGV: 8481.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 8491.88Skamil break; 8501.88Skamil case SIGILL: 8511.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 8521.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 8531.88Skamil break; 8541.88Skamil case SIGFPE: 8551.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 8561.88Skamil break; 8571.88Skamil case SIGBUS: 8581.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 8591.88Skamil break; 8601.88Skamil } 8611.88Skamil 8621.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 8631.88Skamil 8641.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8651.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8661.88Skamil 8671.88Skamil validate_status_signaled(status, SIGKILL, 0); 8681.88Skamil 8691.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8701.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 8711.88Skamil} 8721.88Skamil 8731.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig) \ 8741.88SkamilATF_TC(test); \ 8751.88SkamilATF_TC_HEAD(test, tc) \ 8761.88Skamil{ \ 8771.88Skamil atf_tc_set_md_var(tc, "descr", \ 8781.88Skamil "Verify ignored crash signal " #sig " in a child after " \ 8791.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 8801.88Skamil} \ 8811.88Skamil \ 8821.88SkamilATF_TC_BODY(test, tc) \ 8831.88Skamil{ \ 8841.88Skamil \ 8851.88Skamil traceme_signalignored_crash(sig); \ 8861.88Skamil} 8871.88Skamil 8881.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP) 8891.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV) 8901.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL) 8911.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE) 8921.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS) 8931.88Skamil 8941.88Skamil/// ---------------------------------------------------------------------------- 8951.88Skamil 8961.88Skamilstatic void 8971.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught) 8981.1Skamil{ 8991.1Skamil const int exitval = 5; 9001.34Skamil const int sigval = SIGSTOP; 9011.1Skamil pid_t child, wpid; 9021.1Skamil struct sigaction sa; 9031.1Skamil#if defined(TWAIT_HAVE_STATUS) 9041.1Skamil int status; 9051.1Skamil#endif 9061.61Skre struct ptrace_siginfo info; 9071.1Skamil 9081.45Skamil memset(&info, 0, sizeof(info)); 9091.45Skamil 9101.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 9111.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 9121.1Skamil if (child == 0) { 9131.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 9141.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 9151.1Skamil 9161.34Skamil sa.sa_handler = sah; 9171.1Skamil sa.sa_flags = SA_SIGINFO; 9181.1Skamil sigemptyset(&sa.sa_mask); 9191.1Skamil 9201.1Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 9211.1Skamil 9221.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 9231.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 9241.1Skamil 9251.34Skamil FORKEE_ASSERT_EQ(*traceme_caught, 1); 9261.1Skamil 9271.13Schristos DPRINTF("Before exiting of the child process\n"); 9281.1Skamil _exit(exitval); 9291.1Skamil } 9301.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 9311.1Skamil 9321.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9331.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9341.1Skamil 9351.1Skamil validate_status_stopped(status, sigval); 9361.1Skamil 9371.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 9381.61Skre SYSCALL_REQUIRE( 9391.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 9401.45Skamil 9411.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 9421.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 9431.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 9441.45Skamil info.psi_siginfo.si_errno); 9451.45Skamil 9461.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 9471.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 9481.45Skamil 9491.13Schristos DPRINTF("Before resuming the child process where it left off and with " 9501.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 9511.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 9521.1Skamil 9531.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9541.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9551.1Skamil 9561.1Skamil validate_status_exited(status, exitval); 9571.1Skamil 9581.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 9591.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 9601.1Skamil} 9611.1Skamil 9621.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig) \ 9631.61SkreATF_TC(test); \ 9641.61SkreATF_TC_HEAD(test, tc) \ 9651.61Skre{ \ 9661.61Skre atf_tc_set_md_var(tc, "descr", \ 9671.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 9681.61Skre "handled correctly and caught by a signal handler"); \ 9691.61Skre} \ 9701.61Skre \ 9711.61Skrestatic int test##_caught = 0; \ 9721.61Skre \ 9731.61Skrestatic void \ 9741.61Skretest##_sighandler(int arg) \ 9751.61Skre{ \ 9761.61Skre FORKEE_ASSERT_EQ(arg, sig); \ 9771.61Skre \ 9781.61Skre ++ test##_caught; \ 9791.61Skre} \ 9801.61Skre \ 9811.61SkreATF_TC_BODY(test, tc) \ 9821.61Skre{ \ 9831.61Skre \ 9841.61Skre traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \ 9851.34Skamil} 9861.34Skamil 9871.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered. 9881.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */ 9891.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP) /* hangup */ 9901.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */ 9911.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */ 9921.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */ 9931.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */ 9941.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */ 9951.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */ 9961.34Skamil 9971.34Skamil/// ---------------------------------------------------------------------------- 9981.34Skamil 9991.35Skamilstatic void 10001.50Skamiltraceme_sendsignal_masked(int sigsent) 10011.50Skamil{ 10021.50Skamil const int exitval = 5; 10031.50Skamil const int sigval = SIGSTOP; 10041.50Skamil pid_t child, wpid; 10051.50Skamil sigset_t set; 10061.50Skamil#if defined(TWAIT_HAVE_STATUS) 10071.50Skamil int status; 10081.50Skamil#endif 10091.61Skre struct ptrace_siginfo info; 10101.50Skamil 10111.50Skamil memset(&info, 0, sizeof(info)); 10121.50Skamil 10131.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 10141.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 10151.50Skamil if (child == 0) { 10161.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 10171.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 10181.50Skamil 10191.50Skamil sigemptyset(&set); 10201.50Skamil sigaddset(&set, sigsent); 10211.50Skamil FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 10221.50Skamil 10231.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 10241.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 10251.50Skamil 10261.50Skamil _exit(exitval); 10271.50Skamil } 10281.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 10291.50Skamil 10301.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10311.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10321.50Skamil 10331.50Skamil validate_status_stopped(status, sigval); 10341.50Skamil 10351.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 10361.61Skre SYSCALL_REQUIRE( 10371.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 10381.50Skamil 10391.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 10401.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 10411.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 10421.50Skamil info.psi_siginfo.si_errno); 10431.50Skamil 10441.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 10451.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 10461.50Skamil 10471.50Skamil DPRINTF("Before resuming the child process where it left off and with " 10481.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 10491.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 10501.50Skamil 10511.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10521.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10531.50Skamil 10541.50Skamil validate_status_exited(status, exitval); 10551.50Skamil 10561.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 10571.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 10581.50Skamil} 10591.50Skamil 10601.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig) \ 10611.61SkreATF_TC(test); \ 10621.61SkreATF_TC_HEAD(test, tc) \ 10631.61Skre{ \ 10641.61Skre atf_tc_set_md_var(tc, "descr", \ 10651.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 10661.61Skre "handled correctly and the signal is masked by SIG_BLOCK"); \ 10671.61Skre} \ 10681.61Skre \ 10691.61SkreATF_TC_BODY(test, tc) \ 10701.61Skre{ \ 10711.61Skre \ 10721.61Skre traceme_sendsignal_masked(sig); \ 10731.50Skamil} 10741.50Skamil 10751.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 10761.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */ 10771.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP) /* hangup */ 10781.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */ 10791.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */ 10801.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */ 10811.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */ 10821.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */ 10831.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */ 10841.50Skamil 10851.50Skamil/// ---------------------------------------------------------------------------- 10861.50Skamil 10871.50Skamilstatic void 10881.50Skamiltraceme_sendsignal_ignored(int sigsent) 10891.50Skamil{ 10901.50Skamil const int exitval = 5; 10911.50Skamil const int sigval = SIGSTOP; 10921.50Skamil pid_t child, wpid; 10931.50Skamil struct sigaction sa; 10941.50Skamil#if defined(TWAIT_HAVE_STATUS) 10951.50Skamil int status; 10961.50Skamil#endif 10971.61Skre struct ptrace_siginfo info; 10981.50Skamil 10991.50Skamil memset(&info, 0, sizeof(info)); 11001.50Skamil 11011.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 11021.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 11031.50Skamil if (child == 0) { 11041.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 11051.61Skre 11061.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 11071.50Skamil 11081.50Skamil memset(&sa, 0, sizeof(sa)); 11091.50Skamil sa.sa_handler = SIG_IGN; 11101.50Skamil sigemptyset(&sa.sa_mask); 11111.50Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 11121.50Skamil 11131.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 11141.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 11151.50Skamil 11161.50Skamil _exit(exitval); 11171.50Skamil } 11181.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 11191.50Skamil 11201.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11211.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11221.50Skamil 11231.50Skamil validate_status_stopped(status, sigval); 11241.50Skamil 11251.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 11261.61Skre SYSCALL_REQUIRE( 11271.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 11281.50Skamil 11291.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 11301.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 11311.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 11321.50Skamil info.psi_siginfo.si_errno); 11331.50Skamil 11341.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 11351.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 11361.50Skamil 11371.50Skamil DPRINTF("Before resuming the child process where it left off and with " 11381.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 11391.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 11401.50Skamil 11411.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11421.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11431.50Skamil 11441.50Skamil validate_status_exited(status, exitval); 11451.50Skamil 11461.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 11471.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 11481.50Skamil} 11491.50Skamil 11501.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig) \ 11511.61SkreATF_TC(test); \ 11521.61SkreATF_TC_HEAD(test, tc) \ 11531.61Skre{ \ 11541.61Skre atf_tc_set_md_var(tc, "descr", \ 11551.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 11561.61Skre "handled correctly and the signal is masked by SIG_IGN"); \ 11571.61Skre} \ 11581.61Skre \ 11591.61SkreATF_TC_BODY(test, tc) \ 11601.61Skre{ \ 11611.61Skre \ 11621.61Skre traceme_sendsignal_ignored(sig); \ 11631.50Skamil} 11641.50Skamil 11651.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 11661.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */ 11671.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP) /* hangup */ 11681.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */ 11691.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */ 11701.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */ 11711.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */ 11721.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */ 11731.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */ 11741.50Skamil 11751.50Skamil/// ---------------------------------------------------------------------------- 11761.50Skamil 11771.50Skamilstatic void 11781.50Skamiltraceme_sendsignal_simple(int sigsent) 11791.1Skamil{ 11801.35Skamil const int sigval = SIGSTOP; 11811.35Skamil int exitval = 0; 11821.1Skamil pid_t child, wpid; 11831.1Skamil#if defined(TWAIT_HAVE_STATUS) 11841.1Skamil int status; 11851.85Skamil int expect_core; 11861.85Skamil 11871.85Skamil switch (sigsent) { 11881.85Skamil case SIGABRT: 11891.85Skamil case SIGTRAP: 11901.85Skamil case SIGBUS: 11911.85Skamil case SIGILL: 11921.85Skamil case SIGFPE: 11931.85Skamil case SIGSEGV: 11941.85Skamil expect_core = 1; 11951.85Skamil break; 11961.85Skamil default: 11971.85Skamil expect_core = 0; 11981.85Skamil break; 11991.85Skamil } 12001.1Skamil#endif 12011.61Skre struct ptrace_siginfo info; 12021.1Skamil 12031.45Skamil memset(&info, 0, sizeof(info)); 12041.45Skamil 12051.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 12061.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 12071.1Skamil if (child == 0) { 12081.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 12091.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 12101.1Skamil 12111.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 12121.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 12131.1Skamil 12141.35Skamil switch (sigsent) { 12151.35Skamil case SIGCONT: 12161.48Skamil case SIGSTOP: 12171.35Skamil _exit(exitval); 12181.35Skamil default: 12191.35Skamil /* NOTREACHED */ 12201.35Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 12211.35Skamil } 12221.1Skamil } 12231.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 12241.1Skamil 12251.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12261.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12271.1Skamil 12281.1Skamil validate_status_stopped(status, sigval); 12291.1Skamil 12301.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 12311.61Skre SYSCALL_REQUIRE( 12321.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 12331.45Skamil 12341.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12351.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 12361.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12371.45Skamil info.psi_siginfo.si_errno); 12381.45Skamil 12391.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12401.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12411.45Skamil 12421.13Schristos DPRINTF("Before resuming the child process where it left off and with " 12431.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 12441.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 12451.1Skamil 12461.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12471.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12481.1Skamil 12491.35Skamil switch (sigsent) { 12501.48Skamil case SIGSTOP: 12511.48Skamil validate_status_stopped(status, sigsent); 12521.48Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 12531.61Skre "child\n"); 12541.48Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 12551.61Skre sizeof(info)) != -1); 12561.48Skamil 12571.48Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12581.48Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 12591.61Skre "si_errno=%#x\n", 12601.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12611.61Skre info.psi_siginfo.si_errno); 12621.48Skamil 12631.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12641.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12651.48Skamil 12661.48Skamil DPRINTF("Before resuming the child process where it left off " 12671.61Skre "and with signal %s to be sent\n", strsignal(sigsent)); 12681.48Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 12691.48Skamil 12701.48Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12711.48Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 12721.61Skre child); 12731.48Skamil /* FALLTHROUGH */ 12741.35Skamil case SIGCONT: 12751.35Skamil validate_status_exited(status, exitval); 12761.35Skamil break; 12771.35Skamil default: 12781.35Skamil validate_status_signaled(status, sigsent, expect_core); 12791.35Skamil break; 12801.35Skamil } 12811.1Skamil 12821.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 12831.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 12841.1Skamil} 12851.1Skamil 12861.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig) \ 12871.61SkreATF_TC(test); \ 12881.61SkreATF_TC_HEAD(test, tc) \ 12891.61Skre{ \ 12901.61Skre atf_tc_set_md_var(tc, "descr", \ 12911.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 12921.61Skre "handled correctly in a child without a signal handler"); \ 12931.61Skre} \ 12941.61Skre \ 12951.61SkreATF_TC_BODY(test, tc) \ 12961.61Skre{ \ 12971.61Skre \ 12981.61Skre traceme_sendsignal_simple(sig); \ 12991.35Skamil} 13001.35Skamil 13011.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/ 13021.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/ 13031.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */ 13041.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP) /* hangup */ 13051.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */ 13061.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */ 13071.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */ 13081.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */ 13091.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */ 13101.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */ 13111.35Skamil 13121.35Skamil/// ---------------------------------------------------------------------------- 13131.35Skamil 13141.37SkamilATF_TC(traceme_pid1_parent); 13151.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc) 13161.37Skamil{ 13171.37Skamil atf_tc_set_md_var(tc, "descr", 13181.37Skamil "Verify that PT_TRACE_ME is not allowed when our parent is PID1"); 13191.37Skamil} 13201.37Skamil 13211.37SkamilATF_TC_BODY(traceme_pid1_parent, tc) 13221.37Skamil{ 13231.37Skamil struct msg_fds parent_child; 13241.37Skamil int exitval_child1 = 1, exitval_child2 = 2; 13251.37Skamil pid_t child1, child2, wpid; 13261.37Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 13271.37Skamil#if defined(TWAIT_HAVE_STATUS) 13281.37Skamil int status; 13291.37Skamil#endif 13301.37Skamil 13311.37Skamil SYSCALL_REQUIRE(msg_open(&parent_child) == 0); 13321.37Skamil 13331.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13341.37Skamil SYSCALL_REQUIRE((child1 = fork()) != -1); 13351.37Skamil if (child1 == 0) { 13361.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13371.37Skamil SYSCALL_REQUIRE((child2 = fork()) != -1); 13381.37Skamil if (child2 != 0) { 13391.37Skamil DPRINTF("Parent process PID=%d, child2's PID=%d\n", 13401.61Skre getpid(), child2); 13411.37Skamil _exit(exitval_child1); 13421.37Skamil } 13431.37Skamil CHILD_FROM_PARENT("exit child1", parent_child, msg); 13441.37Skamil 13451.37Skamil DPRINTF("Assert that our parent is PID1 (initproc)\n"); 13461.37Skamil FORKEE_ASSERT_EQ(getppid(), 1); 13471.37Skamil 13481.37Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 13491.37Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1); 13501.37Skamil SYSCALL_REQUIRE_ERRNO(errno, EPERM); 13511.37Skamil 13521.37Skamil CHILD_TO_PARENT("child2 exiting", parent_child, msg); 13531.37Skamil 13541.37Skamil _exit(exitval_child2); 13551.37Skamil } 13561.37Skamil DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1); 13571.37Skamil 13581.37Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 13591.61Skre TWAIT_REQUIRE_SUCCESS( 13601.61Skre wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1); 13611.37Skamil 13621.37Skamil validate_status_exited(status, exitval_child1); 13631.37Skamil 13641.37Skamil DPRINTF("Notify that child1 is dead\n"); 13651.37Skamil PARENT_TO_CHILD("exit child1", parent_child, msg); 13661.37Skamil 13671.37Skamil DPRINTF("Wait for exiting of child2\n"); 13681.37Skamil PARENT_FROM_CHILD("child2 exiting", parent_child, msg); 13691.37Skamil} 13701.37Skamil 13711.37Skamil/// ---------------------------------------------------------------------------- 13721.37Skamil 13731.40Skamilstatic void 13741.40Skamiltraceme_vfork_raise(int sigval) 13751.40Skamil{ 13761.46Skamil const int exitval = 5, exitval_watcher = 10; 13771.46Skamil pid_t child, parent, watcher, wpid; 13781.46Skamil int rv; 13791.40Skamil#if defined(TWAIT_HAVE_STATUS) 13801.40Skamil int status; 13811.85Skamil 13821.85Skamil /* volatile workarounds GCC -Werror=clobbered */ 13831.85Skamil volatile int expect_core; 13841.85Skamil 13851.85Skamil switch (sigval) { 13861.85Skamil case SIGABRT: 13871.85Skamil case SIGTRAP: 13881.85Skamil case SIGBUS: 13891.85Skamil case SIGILL: 13901.85Skamil case SIGFPE: 13911.85Skamil case SIGSEGV: 13921.85Skamil expect_core = 1; 13931.85Skamil break; 13941.85Skamil default: 13951.85Skamil expect_core = 0; 13961.85Skamil break; 13971.85Skamil } 13981.40Skamil#endif 13991.40Skamil 14001.46Skamil /* 14011.46Skamil * Spawn a dedicated thread to watch for a stopped child and emit 14021.46Skamil * the SIGKILL signal to it. 14031.46Skamil * 14041.46Skamil * vfork(2) might clobber watcher, this means that it's safer and 14051.46Skamil * simpler to reparent this process to initproc and forget about it. 14061.46Skamil */ 14071.46Skamil if (sigval == SIGSTOP) { 14081.46Skamil parent = getpid(); 14091.46Skamil 14101.46Skamil watcher = fork(); 14111.46Skamil ATF_REQUIRE(watcher != 1); 14121.46Skamil if (watcher == 0) { 14131.46Skamil /* Double fork(2) trick to reparent to initproc */ 14141.46Skamil watcher = fork(); 14151.46Skamil FORKEE_ASSERT_NEQ(watcher, -1); 14161.46Skamil if (watcher != 0) 14171.46Skamil _exit(exitval_watcher); 14181.46Skamil 14191.46Skamil child = await_stopped_child(parent); 14201.46Skamil 14211.46Skamil errno = 0; 14221.46Skamil rv = kill(child, SIGKILL); 14231.46Skamil FORKEE_ASSERT_EQ(rv, 0); 14241.46Skamil FORKEE_ASSERT_EQ(errno, 0); 14251.46Skamil 14261.46Skamil /* This exit value will be collected by initproc */ 14271.46Skamil _exit(0); 14281.46Skamil } 14291.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14301.46Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0), 14311.61Skre watcher); 14321.46Skamil 14331.46Skamil validate_status_exited(status, exitval_watcher); 14341.46Skamil 14351.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14361.61Skre TWAIT_REQUIRE_FAILURE(ECHILD, 14371.61Skre wpid = TWAIT_GENERIC(watcher, &status, 0)); 14381.46Skamil } 14391.46Skamil 14401.40Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 14411.40Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 14421.40Skamil if (child == 0) { 14431.40Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 14441.40Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 14451.40Skamil 14461.40Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 14471.40Skamil FORKEE_ASSERT(raise(sigval) == 0); 14481.40Skamil 14491.40Skamil switch (sigval) { 14501.46Skamil case SIGSTOP: 14511.40Skamil case SIGKILL: 14521.40Skamil case SIGABRT: 14531.40Skamil case SIGHUP: 14541.85Skamil case SIGTRAP: 14551.85Skamil case SIGBUS: 14561.85Skamil case SIGILL: 14571.85Skamil case SIGFPE: 14581.85Skamil case SIGSEGV: 14591.40Skamil /* NOTREACHED */ 14601.40Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 14611.70Smrg __unreachable(); 14621.40Skamil default: 14631.40Skamil DPRINTF("Before exiting of the child process\n"); 14641.40Skamil _exit(exitval); 14651.40Skamil } 14661.40Skamil } 14671.40Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 14681.40Skamil 14691.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14701.40Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 14711.40Skamil 14721.40Skamil switch (sigval) { 14731.40Skamil case SIGKILL: 14741.40Skamil case SIGABRT: 14751.40Skamil case SIGHUP: 14761.85Skamil case SIGTRAP: 14771.85Skamil case SIGBUS: 14781.85Skamil case SIGILL: 14791.85Skamil case SIGFPE: 14801.85Skamil case SIGSEGV: 14811.40Skamil validate_status_signaled(status, sigval, expect_core); 14821.40Skamil break; 14831.40Skamil case SIGSTOP: 14841.46Skamil validate_status_signaled(status, SIGKILL, 0); 14851.46Skamil break; 14861.40Skamil case SIGCONT: 14871.47Skamil case SIGTSTP: 14881.47Skamil case SIGTTIN: 14891.47Skamil case SIGTTOU: 14901.40Skamil validate_status_exited(status, exitval); 14911.40Skamil break; 14921.40Skamil default: 14931.40Skamil /* NOTREACHED */ 14941.40Skamil ATF_REQUIRE(0 && "NOT IMPLEMENTED"); 14951.40Skamil break; 14961.40Skamil } 14971.40Skamil 14981.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14991.40Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15001.40Skamil} 15011.40Skamil 15021.61Skre#define TRACEME_VFORK_RAISE(test, sig) \ 15031.61SkreATF_TC(test); \ 15041.61SkreATF_TC_HEAD(test, tc) \ 15051.61Skre{ \ 15061.61Skre atf_tc_set_md_var(tc, "descr", \ 15071.61Skre "Verify PT_TRACE_ME followed by raise of " #sig " in a " \ 15081.61Skre "vfork(2)ed child"); \ 15091.61Skre} \ 15101.61Skre \ 15111.61SkreATF_TC_BODY(test, tc) \ 15121.61Skre{ \ 15131.61Skre \ 15141.61Skre traceme_vfork_raise(sig); \ 15151.40Skamil} 15161.40Skamil 15171.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */ 15181.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */ 15191.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */ 15201.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */ 15211.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */ 15221.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */ 15231.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP) /* hangup */ 15241.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */ 15251.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */ 15261.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */ 15271.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */ 15281.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */ 15291.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */ 15301.40Skamil 15311.40Skamil/// ---------------------------------------------------------------------------- 15321.40Skamil 15331.52Skamilstatic void 15341.52Skamiltraceme_vfork_crash(int sig) 15351.41Skamil{ 15361.41Skamil pid_t child, wpid; 15371.41Skamil#if defined(TWAIT_HAVE_STATUS) 15381.41Skamil int status; 15391.41Skamil#endif 15401.41Skamil 15411.71Skamil#ifndef PTRACE_ILLEGAL_ASM 15421.71Skamil if (sig == SIGILL) 15431.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 15441.71Skamil#endif 15451.71Skamil 15461.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 15471.114Skamil atf_tc_skip("FP exceptions are not supported"); 15481.114Skamil 15491.41Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 15501.41Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 15511.41Skamil if (child == 0) { 15521.41Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 15531.41Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 15541.41Skamil 15551.52Skamil DPRINTF("Before executing a trap\n"); 15561.52Skamil switch (sig) { 15571.52Skamil case SIGTRAP: 15581.52Skamil trigger_trap(); 15591.52Skamil break; 15601.52Skamil case SIGSEGV: 15611.52Skamil trigger_segv(); 15621.52Skamil break; 15631.52Skamil case SIGILL: 15641.52Skamil trigger_ill(); 15651.52Skamil break; 15661.52Skamil case SIGFPE: 15671.52Skamil trigger_fpe(); 15681.52Skamil break; 15691.52Skamil case SIGBUS: 15701.52Skamil trigger_bus(); 15711.52Skamil break; 15721.52Skamil default: 15731.52Skamil /* NOTREACHED */ 15741.52Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15751.52Skamil } 15761.41Skamil 15771.41Skamil /* NOTREACHED */ 15781.41Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15791.41Skamil } 15801.41Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 15811.41Skamil 15821.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15831.41Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 15841.41Skamil 15851.52Skamil validate_status_signaled(status, sig, 1); 15861.41Skamil 15871.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15881.41Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15891.41Skamil} 15901.41Skamil 15911.61Skre#define TRACEME_VFORK_CRASH(test, sig) \ 15921.61SkreATF_TC(test); \ 15931.61SkreATF_TC_HEAD(test, tc) \ 15941.61Skre{ \ 15951.61Skre atf_tc_set_md_var(tc, "descr", \ 15961.61Skre "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 15971.61Skre "vfork(2)ed child"); \ 15981.61Skre} \ 15991.61Skre \ 16001.61SkreATF_TC_BODY(test, tc) \ 16011.61Skre{ \ 16021.61Skre \ 16031.61Skre traceme_vfork_crash(sig); \ 16041.52Skamil} 16051.52Skamil 16061.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP) 16071.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV) 16081.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL) 16091.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE) 16101.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS) 16111.52Skamil 16121.41Skamil/// ---------------------------------------------------------------------------- 16131.41Skamil 16141.92Skamilstatic void 16151.92Skamiltraceme_vfork_signalmasked_crash(int sig) 16161.92Skamil{ 16171.92Skamil pid_t child, wpid; 16181.92Skamil#if defined(TWAIT_HAVE_STATUS) 16191.92Skamil int status; 16201.92Skamil#endif 16211.92Skamil sigset_t intmask; 16221.92Skamil 16231.92Skamil#ifndef PTRACE_ILLEGAL_ASM 16241.92Skamil if (sig == SIGILL) 16251.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 16261.92Skamil#endif 16271.92Skamil 16281.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 16291.114Skamil atf_tc_skip("FP exceptions are not supported"); 16301.114Skamil 16311.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 16321.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 16331.92Skamil if (child == 0) { 16341.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 16351.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 16361.92Skamil 16371.92Skamil sigemptyset(&intmask); 16381.92Skamil sigaddset(&intmask, sig); 16391.92Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 16401.92Skamil 16411.92Skamil DPRINTF("Before executing a trap\n"); 16421.92Skamil switch (sig) { 16431.92Skamil case SIGTRAP: 16441.92Skamil trigger_trap(); 16451.92Skamil break; 16461.92Skamil case SIGSEGV: 16471.92Skamil trigger_segv(); 16481.92Skamil break; 16491.92Skamil case SIGILL: 16501.92Skamil trigger_ill(); 16511.92Skamil break; 16521.92Skamil case SIGFPE: 16531.92Skamil trigger_fpe(); 16541.92Skamil break; 16551.92Skamil case SIGBUS: 16561.92Skamil trigger_bus(); 16571.92Skamil break; 16581.92Skamil default: 16591.92Skamil /* NOTREACHED */ 16601.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16611.92Skamil } 16621.92Skamil 16631.92Skamil /* NOTREACHED */ 16641.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16651.92Skamil } 16661.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 16671.92Skamil 16681.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16691.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 16701.92Skamil 16711.92Skamil validate_status_signaled(status, sig, 1); 16721.92Skamil 16731.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16741.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 16751.92Skamil} 16761.92Skamil 16771.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig) \ 16781.92SkamilATF_TC(test); \ 16791.92SkamilATF_TC_HEAD(test, tc) \ 16801.92Skamil{ \ 16811.92Skamil atf_tc_set_md_var(tc, "descr", \ 16821.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16831.92Skamil "vfork(2)ed child with a masked signal"); \ 16841.92Skamil} \ 16851.92Skamil \ 16861.92SkamilATF_TC_BODY(test, tc) \ 16871.92Skamil{ \ 16881.92Skamil \ 16891.92Skamil traceme_vfork_signalmasked_crash(sig); \ 16901.92Skamil} 16911.92Skamil 16921.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP) 16931.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV) 16941.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL) 16951.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE) 16961.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS) 16971.92Skamil 16981.92Skamil/// ---------------------------------------------------------------------------- 16991.92Skamil 17001.92Skamilstatic void 17011.92Skamiltraceme_vfork_signalignored_crash(int sig) 17021.92Skamil{ 17031.92Skamil pid_t child, wpid; 17041.92Skamil#if defined(TWAIT_HAVE_STATUS) 17051.92Skamil int status; 17061.92Skamil#endif 17071.92Skamil struct sigaction sa; 17081.92Skamil 17091.92Skamil#ifndef PTRACE_ILLEGAL_ASM 17101.92Skamil if (sig == SIGILL) 17111.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 17121.92Skamil#endif 17131.92Skamil 17141.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 17151.114Skamil atf_tc_skip("FP exceptions are not supported"); 17161.114Skamil 17171.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 17181.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 17191.92Skamil if (child == 0) { 17201.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 17211.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 17221.92Skamil 17231.92Skamil memset(&sa, 0, sizeof(sa)); 17241.92Skamil sa.sa_handler = SIG_IGN; 17251.92Skamil sigemptyset(&sa.sa_mask); 17261.92Skamil 17271.92Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 17281.92Skamil 17291.92Skamil DPRINTF("Before executing a trap\n"); 17301.92Skamil switch (sig) { 17311.92Skamil case SIGTRAP: 17321.92Skamil trigger_trap(); 17331.92Skamil break; 17341.92Skamil case SIGSEGV: 17351.92Skamil trigger_segv(); 17361.92Skamil break; 17371.92Skamil case SIGILL: 17381.92Skamil trigger_ill(); 17391.92Skamil break; 17401.92Skamil case SIGFPE: 17411.92Skamil trigger_fpe(); 17421.92Skamil break; 17431.92Skamil case SIGBUS: 17441.92Skamil trigger_bus(); 17451.92Skamil break; 17461.92Skamil default: 17471.92Skamil /* NOTREACHED */ 17481.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17491.92Skamil } 17501.92Skamil 17511.92Skamil /* NOTREACHED */ 17521.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17531.92Skamil } 17541.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 17551.92Skamil 17561.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17571.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17581.92Skamil 17591.92Skamil validate_status_signaled(status, sig, 1); 17601.92Skamil 17611.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17621.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 17631.92Skamil} 17641.92Skamil 17651.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig) \ 17661.92SkamilATF_TC(test); \ 17671.92SkamilATF_TC_HEAD(test, tc) \ 17681.92Skamil{ \ 17691.92Skamil atf_tc_set_md_var(tc, "descr", \ 17701.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 17711.92Skamil "vfork(2)ed child with ignored signal"); \ 17721.92Skamil} \ 17731.92Skamil \ 17741.92SkamilATF_TC_BODY(test, tc) \ 17751.92Skamil{ \ 17761.92Skamil \ 17771.92Skamil traceme_vfork_signalignored_crash(sig); \ 17781.92Skamil} 17791.92Skamil 17801.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap, 17811.92Skamil SIGTRAP) 17821.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv, 17831.92Skamil SIGSEGV) 17841.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill, 17851.92Skamil SIGILL) 17861.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe, 17871.92Skamil SIGFPE) 17881.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus, 17891.92Skamil SIGBUS) 17901.92Skamil 17911.92Skamil/// ---------------------------------------------------------------------------- 17921.92Skamil 17931.96Skamilstatic void 17941.96Skamiltraceme_vfork_exec(bool masked, bool ignored) 17951.43Skamil{ 17961.43Skamil const int sigval = SIGTRAP; 17971.43Skamil pid_t child, wpid; 17981.43Skamil#if defined(TWAIT_HAVE_STATUS) 17991.43Skamil int status; 18001.43Skamil#endif 18011.96Skamil struct sigaction sa; 18021.61Skre struct ptrace_siginfo info; 18031.96Skamil sigset_t intmask; 18041.96Skamil struct kinfo_proc2 kp; 18051.96Skamil size_t len = sizeof(kp); 18061.96Skamil 18071.96Skamil int name[6]; 18081.96Skamil const size_t namelen = __arraycount(name); 18091.96Skamil ki_sigset_t kp_sigmask; 18101.96Skamil ki_sigset_t kp_sigignore; 18111.43Skamil 18121.43Skamil memset(&info, 0, sizeof(info)); 18131.43Skamil 18141.43Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 18151.43Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 18161.43Skamil if (child == 0) { 18171.43Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 18181.43Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 18191.43Skamil 18201.96Skamil if (masked) { 18211.96Skamil sigemptyset(&intmask); 18221.96Skamil sigaddset(&intmask, sigval); 18231.96Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 18241.96Skamil } 18251.96Skamil 18261.96Skamil if (ignored) { 18271.96Skamil memset(&sa, 0, sizeof(sa)); 18281.96Skamil sa.sa_handler = SIG_IGN; 18291.96Skamil sigemptyset(&sa.sa_mask); 18301.96Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 18311.96Skamil } 18321.96Skamil 18331.43Skamil DPRINTF("Before calling execve(2) from child\n"); 18341.43Skamil execlp("/bin/echo", "/bin/echo", NULL); 18351.43Skamil 18361.43Skamil /* NOTREACHED */ 18371.43Skamil FORKEE_ASSERTX(0 && "Not reached"); 18381.43Skamil } 18391.43Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 18401.43Skamil 18411.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 18421.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 18431.43Skamil 18441.43Skamil validate_status_stopped(status, sigval); 18451.43Skamil 18461.96Skamil name[0] = CTL_KERN, 18471.96Skamil name[1] = KERN_PROC2, 18481.96Skamil name[2] = KERN_PROC_PID; 18491.96Skamil name[3] = getpid(); 18501.96Skamil name[4] = sizeof(kp); 18511.96Skamil name[5] = 1; 18521.96Skamil 18531.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18541.96Skamil 18551.96Skamil if (masked) 18561.96Skamil kp_sigmask = kp.p_sigmask; 18571.96Skamil 18581.96Skamil if (ignored) 18591.96Skamil kp_sigignore = kp.p_sigignore; 18601.96Skamil 18611.96Skamil name[3] = getpid(); 18621.96Skamil 18631.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18641.96Skamil 18651.96Skamil if (masked) { 18661.96Skamil DPRINTF("kp_sigmask=" 18671.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18681.96Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 18691.96Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 18701.96Skamil 18711.96Skamil DPRINTF("kp.p_sigmask=" 18721.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18731.96Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 18741.96Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 18751.96Skamil 18761.96Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 18771.96Skamil sizeof(kp_sigmask))); 18781.96Skamil } 18791.96Skamil 18801.96Skamil if (ignored) { 18811.96Skamil DPRINTF("kp_sigignore=" 18821.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18831.96Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 18841.96Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 18851.96Skamil 18861.96Skamil DPRINTF("kp.p_sigignore=" 18871.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18881.96Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 18891.96Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 18901.96Skamil 18911.96Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 18921.96Skamil sizeof(kp_sigignore))); 18931.96Skamil } 18941.96Skamil 18951.43Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 18961.61Skre SYSCALL_REQUIRE( 18971.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 18981.43Skamil 18991.43Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 19001.43Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 19011.43Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 19021.43Skamil info.psi_siginfo.si_errno); 19031.43Skamil 19041.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 19051.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 19061.43Skamil 19071.43Skamil DPRINTF("Before resuming the child process where it left off and " 19081.43Skamil "without signal to be sent\n"); 19091.43Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 19101.43Skamil 19111.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19121.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 19131.43Skamil 19141.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19151.43Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 19161.43Skamil} 19171.43Skamil 19181.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored) \ 19191.96SkamilATF_TC(test); \ 19201.96SkamilATF_TC_HEAD(test, tc) \ 19211.96Skamil{ \ 19221.96Skamil atf_tc_set_md_var(tc, "descr", \ 19231.96Skamil "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed " \ 19241.96Skamil "child%s%s", masked ? " with masked signal" : "", \ 19251.96Skamil masked ? " with ignored signal" : ""); \ 19261.96Skamil} \ 19271.96Skamil \ 19281.96SkamilATF_TC_BODY(test, tc) \ 19291.96Skamil{ \ 19301.96Skamil \ 19311.96Skamil traceme_vfork_exec(masked, ignored); \ 19321.96Skamil} 19331.96Skamil 19341.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false) 19351.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false) 19361.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true) 19371.96Skamil 19381.43Skamil/// ---------------------------------------------------------------------------- 19391.43Skamil 19401.1Skamil#if defined(TWAIT_HAVE_PID) 19411.51Skamilstatic void 19421.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored) 19431.59Skamil{ 19441.94Skamil const int sigval = SIGSTOP; 19451.59Skamil struct msg_fds parent_tracee, parent_tracer; 19461.59Skamil const int exitval = 10; 19471.59Skamil pid_t tracee, tracer, wpid; 19481.59Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 19491.59Skamil#if defined(TWAIT_HAVE_STATUS) 19501.59Skamil int status; 19511.59Skamil#endif 19521.94Skamil struct sigaction sa; 19531.59Skamil struct ptrace_siginfo info; 19541.94Skamil sigset_t intmask; 19551.94Skamil struct kinfo_proc2 kp; 19561.94Skamil size_t len = sizeof(kp); 19571.94Skamil 19581.94Skamil int name[6]; 19591.94Skamil const size_t namelen = __arraycount(name); 19601.94Skamil ki_sigset_t kp_sigmask; 19611.94Skamil ki_sigset_t kp_sigignore; 19621.61Skre 19631.71Skamil#ifndef PTRACE_ILLEGAL_ASM 19641.71Skamil if (sig == SIGILL) 19651.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 19661.71Skamil#endif 19671.71Skamil 19681.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 19691.114Skamil atf_tc_skip("FP exceptions are not supported"); 19701.114Skamil 19711.59Skamil memset(&info, 0, sizeof(info)); 19721.59Skamil 19731.59Skamil DPRINTF("Spawn tracee\n"); 19741.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 19751.59Skamil tracee = atf_utils_fork(); 19761.59Skamil if (tracee == 0) { 19771.59Skamil // Wait for parent to let us crash 19781.59Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 19791.61Skre 19801.94Skamil if (masked) { 19811.94Skamil sigemptyset(&intmask); 19821.94Skamil sigaddset(&intmask, sig); 19831.94Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 19841.94Skamil } 19851.94Skamil 19861.94Skamil if (ignored) { 19871.94Skamil memset(&sa, 0, sizeof(sa)); 19881.94Skamil sa.sa_handler = SIG_IGN; 19891.94Skamil sigemptyset(&sa.sa_mask); 19901.94Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 19911.94Skamil } 19921.94Skamil 19931.94Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 19941.94Skamil FORKEE_ASSERT(raise(sigval) == 0); 19951.94Skamil 19961.59Skamil DPRINTF("Before executing a trap\n"); 19971.59Skamil switch (sig) { 19981.59Skamil case SIGTRAP: 19991.59Skamil trigger_trap(); 20001.59Skamil break; 20011.59Skamil case SIGSEGV: 20021.59Skamil trigger_segv(); 20031.59Skamil break; 20041.59Skamil case SIGILL: 20051.59Skamil trigger_ill(); 20061.59Skamil break; 20071.59Skamil case SIGFPE: 20081.59Skamil trigger_fpe(); 20091.59Skamil break; 20101.59Skamil case SIGBUS: 20111.59Skamil trigger_bus(); 20121.59Skamil break; 20131.59Skamil default: 20141.59Skamil /* NOTREACHED */ 20151.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20161.59Skamil } 20171.59Skamil 20181.59Skamil /* NOTREACHED */ 20191.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20201.59Skamil } 20211.59Skamil 20221.59Skamil DPRINTF("Spawn debugger\n"); 20231.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 20241.59Skamil tracer = atf_utils_fork(); 20251.59Skamil if (tracer == 0) { 20261.59Skamil /* Fork again and drop parent to reattach to PID 1 */ 20271.59Skamil tracer = atf_utils_fork(); 20281.59Skamil if (tracer != 0) 20291.61Skre _exit(exitval); 20301.59Skamil 20311.59Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 20321.59Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 20331.59Skamil 20341.59Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 20351.59Skamil FORKEE_REQUIRE_SUCCESS( 20361.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20371.59Skamil 20381.59Skamil forkee_status_stopped(status, SIGSTOP); 20391.59Skamil 20401.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20411.94Skamil "traced process\n"); 20421.94Skamil SYSCALL_REQUIRE( 20431.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20441.94Skamil 20451.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20461.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20471.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20481.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20491.94Skamil 20501.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 20511.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 20521.94Skamil 20531.59Skamil /* Resume tracee with PT_CONTINUE */ 20541.59Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 20551.59Skamil 20561.59Skamil /* Inform parent that tracer has attached to tracee */ 20571.59Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 20581.59Skamil 20591.59Skamil /* Wait for parent to tell use that tracee should have exited */ 20601.59Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 20611.59Skamil 20621.59Skamil /* Wait for tracee and assert that it exited */ 20631.59Skamil FORKEE_REQUIRE_SUCCESS( 20641.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20651.59Skamil 20661.94Skamil forkee_status_stopped(status, sigval); 20671.94Skamil 20681.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20691.94Skamil "traced process\n"); 20701.94Skamil SYSCALL_REQUIRE( 20711.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20721.94Skamil 20731.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20741.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20751.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20761.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20771.94Skamil 20781.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 20791.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 20801.94Skamil 20811.94Skamil name[0] = CTL_KERN, 20821.94Skamil name[1] = KERN_PROC2, 20831.94Skamil name[2] = KERN_PROC_PID; 20841.94Skamil name[3] = tracee; 20851.94Skamil name[4] = sizeof(kp); 20861.94Skamil name[5] = 1; 20871.94Skamil 20881.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 20891.94Skamil 20901.94Skamil if (masked) 20911.94Skamil kp_sigmask = kp.p_sigmask; 20921.94Skamil 20931.94Skamil if (ignored) 20941.94Skamil kp_sigignore = kp.p_sigignore; 20951.94Skamil 20961.94Skamil /* Resume tracee with PT_CONTINUE */ 20971.94Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 20981.94Skamil 20991.94Skamil /* Wait for tracee and assert that it exited */ 21001.94Skamil FORKEE_REQUIRE_SUCCESS( 21011.94Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21021.94Skamil 21031.93Skamil forkee_status_stopped(status, sig); 21041.59Skamil 21051.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 21061.61Skre "traced process\n"); 21071.61Skre SYSCALL_REQUIRE( 21081.61Skre ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 21091.59Skamil 21101.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21111.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21121.61Skre "si_errno=%#x\n", info.psi_siginfo.si_signo, 21131.61Skre info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 21141.59Skamil 21151.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig); 21161.94Skamil 21171.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21181.94Skamil 21191.94Skamil if (masked) { 21201.94Skamil DPRINTF("kp_sigmask=" 21211.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21221.94Skamil PRIx32 "\n", 21231.94Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 21241.94Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 21251.94Skamil 21261.94Skamil DPRINTF("kp.p_sigmask=" 21271.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21281.94Skamil PRIx32 "\n", 21291.94Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 21301.94Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 21311.94Skamil 21321.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask, 21331.94Skamil sizeof(kp_sigmask))); 21341.94Skamil } 21351.94Skamil 21361.94Skamil if (ignored) { 21371.94Skamil DPRINTF("kp_sigignore=" 21381.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21391.94Skamil PRIx32 "\n", 21401.94Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 21411.94Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 21421.94Skamil 21431.94Skamil DPRINTF("kp.p_sigignore=" 21441.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21451.94Skamil PRIx32 "\n", 21461.94Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 21471.94Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 21481.94Skamil 21491.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore, 21501.94Skamil sizeof(kp_sigignore))); 21511.94Skamil } 21521.94Skamil 21531.59Skamil switch (sig) { 21541.59Skamil case SIGTRAP: 21551.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 21561.59Skamil break; 21571.59Skamil case SIGSEGV: 21581.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 21591.59Skamil break; 21601.71Skamil case SIGILL: 21611.113Skamil FORKEE_ASSERT(info.psi_siginfo.si_code >= ILL_ILLOPC && 21621.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 21631.71Skamil break; 21641.59Skamil case SIGFPE: 21651.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 21661.59Skamil break; 21671.59Skamil case SIGBUS: 21681.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 21691.59Skamil break; 21701.59Skamil } 21711.59Skamil 21721.59Skamil FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1); 21731.59Skamil DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME); 21741.93Skamil FORKEE_REQUIRE_SUCCESS( 21751.61Skre wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21761.59Skamil 21771.93Skamil forkee_status_signaled(status, SIGKILL, 0); 21781.59Skamil 21791.71Skamil /* Inform parent that tracer is exiting normally */ 21801.71Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 21811.71Skamil 21821.59Skamil DPRINTF("Before exiting of the tracer process\n"); 21831.59Skamil _exit(0 /* collect by initproc */); 21841.59Skamil } 21851.59Skamil 21861.59Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 21871.59Skamil "calling %s()\n", TWAIT_FNAME); 21881.59Skamil TWAIT_REQUIRE_SUCCESS( 21891.59Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 21901.59Skamil 21911.59Skamil validate_status_exited(status, exitval); 21921.59Skamil 21931.59Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 21941.59Skamil TWAIT_FNAME); 21951.59Skamil TWAIT_REQUIRE_SUCCESS( 21961.59Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 21971.59Skamil 21981.59Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 21991.59Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 22001.59Skamil 22011.59Skamil DPRINTF("Resume the tracee and let it crash\n"); 22021.59Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 22031.59Skamil 22041.59Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 22051.59Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 22061.59Skamil 22071.59Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 22081.59Skamil TWAIT_FNAME); 22091.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22101.59Skamil 22111.59Skamil validate_status_signaled(status, SIGKILL, 0); 22121.59Skamil 22131.71Skamil DPRINTF("Await normal exit of tracer\n"); 22141.71Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 22151.71Skamil 22161.59Skamil msg_close(&parent_tracer); 22171.59Skamil msg_close(&parent_tracee); 22181.59Skamil} 22191.59Skamil 22201.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig) \ 22211.61SkreATF_TC(test); \ 22221.61SkreATF_TC_HEAD(test, tc) \ 22231.61Skre{ \ 22241.61Skre atf_tc_set_md_var(tc, "descr", \ 22251.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22261.94Skamil "the debuggee"); \ 22271.61Skre} \ 22281.61Skre \ 22291.61SkreATF_TC_BODY(test, tc) \ 22301.61Skre{ \ 22311.61Skre \ 22321.94Skamil unrelated_tracer_sees_crash(sig, false, false); \ 22331.59Skamil} 22341.59Skamil 22351.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP) 22361.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV) 22371.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL) 22381.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE) 22391.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS) 22401.94Skamil 22411.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig) \ 22421.94SkamilATF_TC(test); \ 22431.94SkamilATF_TC_HEAD(test, tc) \ 22441.94Skamil{ \ 22451.94Skamil atf_tc_set_md_var(tc, "descr", \ 22461.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22471.94Skamil "the debuggee with masked signal"); \ 22481.94Skamil} \ 22491.94Skamil \ 22501.94SkamilATF_TC_BODY(test, tc) \ 22511.94Skamil{ \ 22521.94Skamil \ 22531.94Skamil unrelated_tracer_sees_crash(sig, true, false); \ 22541.94Skamil} 22551.94Skamil 22561.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22571.94Skamil unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP) 22581.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22591.94Skamil unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV) 22601.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22611.94Skamil unrelated_tracer_sees_signalmasked_crash_ill, SIGILL) 22621.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22631.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE) 22641.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22651.94Skamil unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS) 22661.94Skamil 22671.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig) \ 22681.94SkamilATF_TC(test); \ 22691.94SkamilATF_TC_HEAD(test, tc) \ 22701.94Skamil{ \ 22711.94Skamil atf_tc_set_md_var(tc, "descr", \ 22721.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22731.94Skamil "the debuggee with signal ignored"); \ 22741.94Skamil} \ 22751.94Skamil \ 22761.94SkamilATF_TC_BODY(test, tc) \ 22771.94Skamil{ \ 22781.94Skamil \ 22791.94Skamil unrelated_tracer_sees_crash(sig, false, true); \ 22801.94Skamil} 22811.94Skamil 22821.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22831.94Skamil unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP) 22841.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22851.94Skamil unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV) 22861.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22871.94Skamil unrelated_tracer_sees_signalignored_crash_ill, SIGILL) 22881.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22891.94Skamil unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE) 22901.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22911.94Skamil unrelated_tracer_sees_signalignored_crash_bus, SIGBUS) 22921.59Skamil#endif 22931.59Skamil 22941.59Skamil/// ---------------------------------------------------------------------------- 22951.59Skamil 22961.59Skamil#if defined(TWAIT_HAVE_PID) 22971.59Skamilstatic void 22981.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated, 22991.67Skamil bool stopped) 23001.1Skamil{ 23011.51Skamil /* 23021.51Skamil * notimeout - disable timeout in await zombie function 23031.51Skamil * unrelated - attach from unrelated tracer reparented to initproc 23041.67Skamil * stopped - attach to a stopped process 23051.51Skamil */ 23061.1Skamil 23071.1Skamil struct msg_fds parent_tracee, parent_tracer; 23081.1Skamil const int exitval_tracee = 5; 23091.1Skamil const int exitval_tracer = 10; 23101.1Skamil pid_t tracee, tracer, wpid; 23111.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 23121.1Skamil#if defined(TWAIT_HAVE_STATUS) 23131.1Skamil int status; 23141.1Skamil#endif 23151.1Skamil 23161.67Skamil /* 23171.67Skamil * Only a subset of options are supported. 23181.67Skamil */ 23191.67Skamil ATF_REQUIRE((!notimeout && !unrelated && !stopped) || 23201.67Skamil (!notimeout && unrelated && !stopped) || 23211.67Skamil (notimeout && !unrelated && !stopped) || 23221.67Skamil (!notimeout && unrelated && stopped)); 23231.67Skamil 23241.13Schristos DPRINTF("Spawn tracee\n"); 23251.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 23261.1Skamil tracee = atf_utils_fork(); 23271.1Skamil if (tracee == 0) { 23281.67Skamil if (stopped) { 23291.67Skamil DPRINTF("Stop self PID %d\n", getpid()); 23301.67Skamil raise(SIGSTOP); 23311.67Skamil } 23321.67Skamil 23331.1Skamil // Wait for parent to let us exit 23341.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 23351.1Skamil _exit(exitval_tracee); 23361.1Skamil } 23371.1Skamil 23381.13Schristos DPRINTF("Spawn debugger\n"); 23391.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 23401.1Skamil tracer = atf_utils_fork(); 23411.1Skamil if (tracer == 0) { 23421.51Skamil if(unrelated) { 23431.51Skamil /* Fork again and drop parent to reattach to PID 1 */ 23441.51Skamil tracer = atf_utils_fork(); 23451.51Skamil if (tracer != 0) 23461.51Skamil _exit(exitval_tracer); 23471.51Skamil } 23481.51Skamil 23491.67Skamil if (stopped) { 23501.67Skamil DPRINTF("Await for a stopped parent PID %d\n", tracee); 23511.67Skamil await_stopped(tracee); 23521.67Skamil } 23531.67Skamil 23541.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 23551.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 23561.1Skamil 23571.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 23581.1Skamil FORKEE_REQUIRE_SUCCESS( 23591.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23601.1Skamil 23611.1Skamil forkee_status_stopped(status, SIGSTOP); 23621.1Skamil 23631.1Skamil /* Resume tracee with PT_CONTINUE */ 23641.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 23651.1Skamil 23661.1Skamil /* Inform parent that tracer has attached to tracee */ 23671.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 23681.1Skamil 23691.1Skamil /* Wait for parent to tell use that tracee should have exited */ 23701.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 23711.1Skamil 23721.1Skamil /* Wait for tracee and assert that it exited */ 23731.1Skamil FORKEE_REQUIRE_SUCCESS( 23741.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23751.1Skamil 23761.1Skamil forkee_status_exited(status, exitval_tracee); 23771.13Schristos DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee); 23781.1Skamil 23791.13Schristos DPRINTF("Before exiting of the tracer process\n"); 23801.51Skamil _exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer); 23811.51Skamil } 23821.51Skamil 23831.51Skamil if (unrelated) { 23841.51Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 23851.51Skamil "calling %s()\n", TWAIT_FNAME); 23861.51Skamil TWAIT_REQUIRE_SUCCESS( 23871.51Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 23881.51Skamil 23891.51Skamil validate_status_exited(status, exitval_tracer); 23901.51Skamil 23911.51Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 23921.51Skamil TWAIT_FNAME); 23931.51Skamil TWAIT_REQUIRE_SUCCESS( 23941.51Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 23951.1Skamil } 23961.1Skamil 23971.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 23981.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 23991.1Skamil 24001.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 24011.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 24021.1Skamil 24031.13Schristos DPRINTF("Detect that tracee is zombie\n"); 24041.51Skamil if (notimeout) 24051.26Skamil await_zombie_raw(tracee, 0); 24061.26Skamil else 24071.26Skamil await_zombie(tracee); 24081.1Skamil 24091.13Schristos DPRINTF("Assert that there is no status about tracee %d - " 24101.1Skamil "Tracer must detect zombie first - calling %s()\n", tracee, 24111.1Skamil TWAIT_FNAME); 24121.1Skamil TWAIT_REQUIRE_SUCCESS( 24131.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 24141.1Skamil 24151.51Skamil if (unrelated) { 24161.51Skamil DPRINTF("Resume the tracer and let it detect exited tracee\n"); 24171.51Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 24181.51Skamil } else { 24191.51Skamil DPRINTF("Tell the tracer child should have exited\n"); 24201.51Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 24211.51Skamil DPRINTF("Wait for tracer to finish its job and exit - calling " 24221.59Skamil "%s()\n", TWAIT_FNAME); 24231.51Skamil 24241.51Skamil DPRINTF("Wait from tracer child to complete waiting for " 24251.59Skamil "tracee\n"); 24261.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 24271.51Skamil tracer); 24281.1Skamil 24291.51Skamil validate_status_exited(status, exitval_tracer); 24301.51Skamil } 24311.1Skamil 24321.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 24331.1Skamil TWAIT_FNAME); 24341.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24351.1Skamil 24361.1Skamil validate_status_exited(status, exitval_tracee); 24371.1Skamil 24381.1Skamil msg_close(&parent_tracer); 24391.1Skamil msg_close(&parent_tracee); 24401.1Skamil} 24411.26Skamil 24421.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent); 24431.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc) 24441.51Skamil{ 24451.51Skamil atf_tc_set_md_var(tc, "descr", 24461.51Skamil "Assert that tracer sees process termination before the parent"); 24471.51Skamil} 24481.51Skamil 24491.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc) 24501.26Skamil{ 24511.26Skamil 24521.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, false, false); 24531.26Skamil} 24541.26Skamil 24551.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates); 24561.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc) 24571.1Skamil{ 24581.1Skamil atf_tc_set_md_var(tc, "descr", 24591.51Skamil "Assert that await_zombie() in attach1 always finds a single " 24601.51Skamil "process and no other error is reported"); 24611.1Skamil} 24621.1Skamil 24631.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc) 24641.1Skamil{ 24651.51Skamil time_t start, end; 24661.51Skamil double diff; 24671.51Skamil unsigned long N = 0; 24681.1Skamil 24691.51Skamil /* 24701.51Skamil * Reuse this test with tracer_sees_terminaton_before_the_parent_raw(). 24711.51Skamil * This test body isn't specific to this race, however it's just good 24721.51Skamil * enough for this purposes, no need to invent a dedicated code flow. 24731.51Skamil */ 24741.1Skamil 24751.51Skamil start = time(NULL); 24761.51Skamil while (true) { 24771.51Skamil DPRINTF("Step: %lu\n", N); 24781.67Skamil tracer_sees_terminaton_before_the_parent_raw(true, false, 24791.67Skamil false); 24801.51Skamil end = time(NULL); 24811.51Skamil diff = difftime(end, start); 24821.51Skamil if (diff >= 5.0) 24831.51Skamil break; 24841.51Skamil ++N; 24851.1Skamil } 24861.51Skamil DPRINTF("Iterations: %lu\n", N); 24871.51Skamil} 24881.1Skamil 24891.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent); 24901.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc) 24911.51Skamil{ 24921.51Skamil atf_tc_set_md_var(tc, "descr", 24931.51Skamil "Assert that tracer sees process termination before the parent"); 24941.51Skamil} 24951.1Skamil 24961.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc) 24971.51Skamil{ 24981.1Skamil 24991.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, false); 25001.67Skamil} 25011.67Skamil 25021.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process); 25031.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc) 25041.67Skamil{ 25051.67Skamil atf_tc_set_md_var(tc, "descr", 25061.67Skamil "Assert that tracer can attach to an unrelated stopped process"); 25071.67Skamil} 25081.67Skamil 25091.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc) 25101.67Skamil{ 25111.67Skamil 25121.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, true); 25131.1Skamil} 25141.1Skamil#endif 25151.1Skamil 25161.51Skamil/// ---------------------------------------------------------------------------- 25171.51Skamil 25181.66Skamilstatic void 25191.66Skamilparent_attach_to_its_child(bool stopped) 25201.1Skamil{ 25211.1Skamil struct msg_fds parent_tracee; 25221.1Skamil const int exitval_tracee = 5; 25231.1Skamil pid_t tracee, wpid; 25241.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 25251.1Skamil#if defined(TWAIT_HAVE_STATUS) 25261.1Skamil int status; 25271.1Skamil#endif 25281.1Skamil 25291.13Schristos DPRINTF("Spawn tracee\n"); 25301.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 25311.1Skamil tracee = atf_utils_fork(); 25321.1Skamil if (tracee == 0) { 25331.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 25341.13Schristos DPRINTF("Parent should now attach to tracee\n"); 25351.1Skamil 25361.66Skamil if (stopped) { 25371.66Skamil DPRINTF("Stop self PID %d\n", getpid()); 25381.66Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 25391.66Skamil } 25401.66Skamil 25411.1Skamil CHILD_FROM_PARENT("Message 2", parent_tracee, msg); 25421.1Skamil /* Wait for message from the parent */ 25431.1Skamil _exit(exitval_tracee); 25441.1Skamil } 25451.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 25461.57Skamil 25471.66Skamil if (stopped) { 25481.66Skamil DPRINTF("Await for a stopped tracee PID %d\n", tracee); 25491.66Skamil await_stopped(tracee); 25501.66Skamil } 25511.66Skamil 25521.13Schristos DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee); 25531.13Schristos SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 25541.1Skamil 25551.13Schristos DPRINTF("Wait for the stopped tracee process with %s()\n", 25561.1Skamil TWAIT_FNAME); 25571.1Skamil TWAIT_REQUIRE_SUCCESS( 25581.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25591.1Skamil 25601.1Skamil validate_status_stopped(status, SIGSTOP); 25611.1Skamil 25621.13Schristos DPRINTF("Resume tracee with PT_CONTINUE\n"); 25631.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 25641.1Skamil 25651.13Schristos DPRINTF("Let the tracee exit now\n"); 25661.1Skamil PARENT_TO_CHILD("Message 2", parent_tracee, msg); 25671.1Skamil 25681.13Schristos DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME); 25691.1Skamil TWAIT_REQUIRE_SUCCESS( 25701.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25711.1Skamil 25721.1Skamil validate_status_exited(status, exitval_tracee); 25731.1Skamil 25741.13Schristos DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME); 25751.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 25761.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0)); 25771.1Skamil 25781.1Skamil msg_close(&parent_tracee); 25791.1Skamil} 25801.1Skamil 25811.66SkamilATF_TC(parent_attach_to_its_child); 25821.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc) 25831.66Skamil{ 25841.66Skamil atf_tc_set_md_var(tc, "descr", 25851.66Skamil "Assert that tracer parent can PT_ATTACH to its child"); 25861.66Skamil} 25871.66Skamil 25881.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc) 25891.66Skamil{ 25901.66Skamil 25911.66Skamil parent_attach_to_its_child(false); 25921.66Skamil} 25931.66Skamil 25941.66SkamilATF_TC(parent_attach_to_its_stopped_child); 25951.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc) 25961.66Skamil{ 25971.66Skamil atf_tc_set_md_var(tc, "descr", 25981.66Skamil "Assert that tracer parent can PT_ATTACH to its stopped child"); 25991.66Skamil} 26001.66Skamil 26011.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc) 26021.66Skamil{ 26031.66Skamil 26041.66Skamil parent_attach_to_its_child(true); 26051.66Skamil} 26061.66Skamil 26071.51Skamil/// ---------------------------------------------------------------------------- 26081.51Skamil 26091.65Skamilstatic void 26101.65Skamilchild_attach_to_its_parent(bool stopped) 26111.1Skamil{ 26121.1Skamil struct msg_fds parent_tracee; 26131.1Skamil const int exitval_tracer = 5; 26141.1Skamil pid_t tracer, wpid; 26151.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 26161.1Skamil#if defined(TWAIT_HAVE_STATUS) 26171.1Skamil int status; 26181.1Skamil#endif 26191.1Skamil 26201.13Schristos DPRINTF("Spawn tracer\n"); 26211.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 26221.1Skamil tracer = atf_utils_fork(); 26231.1Skamil if (tracer == 0) { 26241.1Skamil /* Wait for message from the parent */ 26251.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 26261.1Skamil 26271.65Skamil if (stopped) { 26281.65Skamil DPRINTF("Await for a stopped parent PID %d\n", 26291.65Skamil getppid()); 26301.65Skamil await_stopped(getppid()); 26311.65Skamil } 26321.65Skamil 26331.13Schristos DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n", 26341.1Skamil getppid()); 26351.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1); 26361.1Skamil 26371.13Schristos DPRINTF("Wait for the stopped parent process with %s()\n", 26381.1Skamil TWAIT_FNAME); 26391.1Skamil FORKEE_REQUIRE_SUCCESS( 26401.1Skamil wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid()); 26411.1Skamil 26421.1Skamil forkee_status_stopped(status, SIGSTOP); 26431.1Skamil 26441.13Schristos DPRINTF("Resume parent with PT_DETACH\n"); 26451.1Skamil FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0) 26461.1Skamil != -1); 26471.1Skamil 26481.1Skamil /* Tell parent we are ready */ 26491.1Skamil CHILD_TO_PARENT("Message 1", parent_tracee, msg); 26501.1Skamil 26511.1Skamil _exit(exitval_tracer); 26521.1Skamil } 26531.1Skamil 26541.13Schristos DPRINTF("Wait for the tracer to become ready\n"); 26551.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 26561.65Skamil 26571.65Skamil if (stopped) { 26581.65Skamil DPRINTF("Stop self PID %d\n", getpid()); 26591.65Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 26601.65Skamil } 26611.65Skamil 26621.13Schristos DPRINTF("Allow the tracer to exit now\n"); 26631.1Skamil PARENT_FROM_CHILD("Message 1", parent_tracee, msg); 26641.1Skamil 26651.13Schristos DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME); 26661.1Skamil TWAIT_REQUIRE_SUCCESS( 26671.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 26681.1Skamil 26691.1Skamil validate_status_exited(status, exitval_tracer); 26701.1Skamil 26711.13Schristos DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME); 26721.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 26731.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0)); 26741.1Skamil 26751.1Skamil msg_close(&parent_tracee); 26761.1Skamil} 26771.1Skamil 26781.65SkamilATF_TC(child_attach_to_its_parent); 26791.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc) 26801.65Skamil{ 26811.65Skamil atf_tc_set_md_var(tc, "descr", 26821.65Skamil "Assert that tracer child can PT_ATTACH to its parent"); 26831.65Skamil} 26841.65Skamil 26851.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc) 26861.65Skamil{ 26871.65Skamil 26881.65Skamil child_attach_to_its_parent(false); 26891.65Skamil} 26901.65Skamil 26911.65SkamilATF_TC(child_attach_to_its_stopped_parent); 26921.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc) 26931.65Skamil{ 26941.65Skamil atf_tc_set_md_var(tc, "descr", 26951.65Skamil "Assert that tracer child can PT_ATTACH to its stopped parent"); 26961.65Skamil} 26971.65Skamil 26981.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc) 26991.65Skamil{ 27001.65Skamil /* 27011.65Skamil * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as 27021.65Skamil * this causes a pipe (established from atf-run) to be broken. 27031.65Skamil * atf-run uses this mechanism to monitor whether a test is alive. 27041.65Skamil * 27051.65Skamil * As a workaround spawn this test as a subprocess. 27061.65Skamil */ 27071.65Skamil 27081.65Skamil const int exitval = 15; 27091.65Skamil pid_t child, wpid; 27101.65Skamil#if defined(TWAIT_HAVE_STATUS) 27111.65Skamil int status; 27121.65Skamil#endif 27131.65Skamil 27141.65Skamil SYSCALL_REQUIRE((child = fork()) != -1); 27151.65Skamil if (child == 0) { 27161.65Skamil child_attach_to_its_parent(true); 27171.65Skamil _exit(exitval); 27181.65Skamil } else { 27191.65Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 27201.65Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 27211.65Skamil 27221.65Skamil validate_status_exited(status, exitval); 27231.65Skamil 27241.65Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 27251.65Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 27261.65Skamil } 27271.65Skamil} 27281.65Skamil 27291.51Skamil/// ---------------------------------------------------------------------------- 27301.51Skamil 27311.1Skamil#if defined(TWAIT_HAVE_PID) 27321.1Skamil 27331.51Skamilenum tracee_sees_its_original_parent_type { 27341.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 27351.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 27361.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS 27371.51Skamil}; 27381.51Skamil 27391.51Skamilstatic void 27401.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type) 27411.1Skamil{ 27421.1Skamil struct msg_fds parent_tracer, parent_tracee; 27431.1Skamil const int exitval_tracee = 5; 27441.1Skamil const int exitval_tracer = 10; 27451.1Skamil pid_t parent, tracee, tracer, wpid; 27461.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 27471.1Skamil#if defined(TWAIT_HAVE_STATUS) 27481.1Skamil int status; 27491.1Skamil#endif 27501.51Skamil /* sysctl(3) - kinfo_proc2 */ 27511.51Skamil int name[CTL_MAXNAME]; 27521.51Skamil struct kinfo_proc2 kp; 27531.51Skamil size_t len = sizeof(kp); 27541.51Skamil unsigned int namelen; 27551.51Skamil 27561.51Skamil /* procfs - status */ 27571.51Skamil FILE *fp; 27581.51Skamil struct stat st; 27591.51Skamil const char *fname = "/proc/curproc/status"; 27601.51Skamil char s_executable[MAXPATHLEN]; 27611.51Skamil int s_pid, s_ppid; 27621.51Skamil int rv; 27631.51Skamil 27641.51Skamil if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) { 27651.61Skre SYSCALL_REQUIRE( 27661.61Skre (rv = stat(fname, &st)) == 0 || (errno == ENOENT)); 27671.61Skre if (rv != 0) 27681.51Skamil atf_tc_skip("/proc/curproc/status not found"); 27691.51Skamil } 27701.1Skamil 27711.13Schristos DPRINTF("Spawn tracee\n"); 27721.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 27731.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 27741.1Skamil tracee = atf_utils_fork(); 27751.1Skamil if (tracee == 0) { 27761.1Skamil parent = getppid(); 27771.1Skamil 27781.1Skamil /* Emit message to the parent */ 27791.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 27801.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 27811.1Skamil 27821.51Skamil switch (type) { 27831.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID: 27841.51Skamil FORKEE_ASSERT_EQ(parent, getppid()); 27851.51Skamil break; 27861.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2: 27871.51Skamil namelen = 0; 27881.51Skamil name[namelen++] = CTL_KERN; 27891.51Skamil name[namelen++] = KERN_PROC2; 27901.51Skamil name[namelen++] = KERN_PROC_PID; 27911.51Skamil name[namelen++] = getpid(); 27921.51Skamil name[namelen++] = len; 27931.51Skamil name[namelen++] = 1; 27941.51Skamil 27951.61Skre FORKEE_ASSERT_EQ( 27961.61Skre sysctl(name, namelen, &kp, &len, NULL, 0), 0); 27971.51Skamil FORKEE_ASSERT_EQ(parent, kp.p_ppid); 27981.51Skamil break; 27991.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS: 28001.51Skamil /* 28011.51Skamil * Format: 28021.51Skamil * EXECUTABLE PID PPID ... 28031.51Skamil */ 28041.51Skamil FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL); 28051.51Skamil fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid); 28061.51Skamil FORKEE_ASSERT_EQ(fclose(fp), 0); 28071.51Skamil FORKEE_ASSERT_EQ(parent, s_ppid); 28081.51Skamil break; 28091.51Skamil } 28101.1Skamil 28111.1Skamil _exit(exitval_tracee); 28121.1Skamil } 28131.13Schristos DPRINTF("Wait for child to record its parent identifier (pid)\n"); 28141.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 28151.1Skamil 28161.13Schristos DPRINTF("Spawn debugger\n"); 28171.1Skamil tracer = atf_utils_fork(); 28181.1Skamil if (tracer == 0) { 28191.1Skamil /* No IPC to communicate with the child */ 28201.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 28211.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 28221.1Skamil 28231.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 28241.1Skamil FORKEE_REQUIRE_SUCCESS( 28251.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28261.1Skamil 28271.1Skamil forkee_status_stopped(status, SIGSTOP); 28281.1Skamil 28291.1Skamil /* Resume tracee with PT_CONTINUE */ 28301.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 28311.1Skamil 28321.1Skamil /* Inform parent that tracer has attached to tracee */ 28331.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 28341.1Skamil 28351.1Skamil /* Wait for parent to tell use that tracee should have exited */ 28361.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 28371.1Skamil 28381.1Skamil /* Wait for tracee and assert that it exited */ 28391.1Skamil FORKEE_REQUIRE_SUCCESS( 28401.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28411.1Skamil 28421.1Skamil forkee_status_exited(status, exitval_tracee); 28431.1Skamil 28441.13Schristos DPRINTF("Before exiting of the tracer process\n"); 28451.1Skamil _exit(exitval_tracer); 28461.1Skamil } 28471.1Skamil 28481.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 28491.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 28501.1Skamil 28511.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 28521.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 28531.1Skamil 28541.13Schristos DPRINTF("Detect that tracee is zombie\n"); 28551.1Skamil await_zombie(tracee); 28561.1Skamil 28571.13Schristos DPRINTF("Assert that there is no status about tracee - " 28581.1Skamil "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME); 28591.1Skamil TWAIT_REQUIRE_SUCCESS( 28601.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 28611.1Skamil 28621.13Schristos DPRINTF("Tell the tracer child should have exited\n"); 28631.1Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 28641.1Skamil 28651.13Schristos DPRINTF("Wait from tracer child to complete waiting for tracee\n"); 28661.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 28671.1Skamil tracer); 28681.1Skamil 28691.1Skamil validate_status_exited(status, exitval_tracer); 28701.1Skamil 28711.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 28721.1Skamil TWAIT_FNAME); 28731.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 28741.1Skamil tracee); 28751.1Skamil 28761.1Skamil validate_status_exited(status, exitval_tracee); 28771.1Skamil 28781.1Skamil msg_close(&parent_tracer); 28791.1Skamil msg_close(&parent_tracee); 28801.1Skamil} 28811.1Skamil 28821.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr) \ 28831.61SkreATF_TC(test); \ 28841.61SkreATF_TC_HEAD(test, tc) \ 28851.61Skre{ \ 28861.61Skre atf_tc_set_md_var(tc, "descr", \ 28871.61Skre "Assert that tracee sees its original parent when being traced " \ 28881.61Skre "(check " descr ")"); \ 28891.61Skre} \ 28901.61Skre \ 28911.61SkreATF_TC_BODY(test, tc) \ 28921.61Skre{ \ 28931.61Skre \ 28941.61Skre tracee_sees_its_original_parent(type); \ 28951.1Skamil} 28961.1Skamil 28971.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 28981.51Skamil tracee_sees_its_original_parent_getppid, 28991.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 29001.51Skamil "getppid(2)"); 29011.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29021.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2, 29031.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 29041.51Skamil "sysctl(3) and kinfo_proc2"); 29051.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29061.51Skamil tracee_sees_its_original_parent_procfs_status, 29071.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS, 29081.51Skamil "the status file in procfs"); 29091.1Skamil#endif 29101.1Skamil 29111.51Skamil/// ---------------------------------------------------------------------------- 29121.1Skamil 29131.53Skamilstatic void 29141.53Skamileventmask_preserved(int event) 29151.1Skamil{ 29161.1Skamil const int exitval = 5; 29171.1Skamil const int sigval = SIGSTOP; 29181.1Skamil pid_t child, wpid; 29191.1Skamil#if defined(TWAIT_HAVE_STATUS) 29201.1Skamil int status; 29211.1Skamil#endif 29221.1Skamil ptrace_event_t set_event, get_event; 29231.1Skamil const int len = sizeof(ptrace_event_t); 29241.1Skamil 29251.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 29261.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 29271.1Skamil if (child == 0) { 29281.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 29291.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 29301.1Skamil 29311.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 29321.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 29331.1Skamil 29341.13Schristos DPRINTF("Before exiting of the child process\n"); 29351.1Skamil _exit(exitval); 29361.1Skamil } 29371.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 29381.1Skamil 29391.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29401.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29411.1Skamil 29421.1Skamil validate_status_stopped(status, sigval); 29431.1Skamil 29441.53Skamil set_event.pe_set_event = event; 29451.61Skre SYSCALL_REQUIRE( 29461.61Skre ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); 29471.61Skre SYSCALL_REQUIRE( 29481.61Skre ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); 29491.1Skamil ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); 29501.1Skamil 29511.13Schristos DPRINTF("Before resuming the child process where it left off and " 29521.1Skamil "without signal to be sent\n"); 29531.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 29541.1Skamil 29551.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29561.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29571.1Skamil 29581.1Skamil validate_status_exited(status, exitval); 29591.1Skamil 29601.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29611.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 29621.1Skamil} 29631.1Skamil 29641.61Skre#define EVENTMASK_PRESERVED(test, event) \ 29651.61SkreATF_TC(test); \ 29661.61SkreATF_TC_HEAD(test, tc) \ 29671.61Skre{ \ 29681.61Skre atf_tc_set_md_var(tc, "descr", \ 29691.61Skre "Verify that eventmask " #event " is preserved"); \ 29701.61Skre} \ 29711.61Skre \ 29721.61SkreATF_TC_BODY(test, tc) \ 29731.61Skre{ \ 29741.61Skre \ 29751.61Skre eventmask_preserved(event); \ 29761.1Skamil} 29771.1Skamil 29781.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0) 29791.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK) 29801.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK) 29811.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE) 29821.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE) 29831.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT) 29841.1Skamil 29851.53Skamil/// ---------------------------------------------------------------------------- 29861.1Skamil 29871.28Skamilstatic void 29881.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork, 29891.105Skamil bool trackvforkdone) 29901.1Skamil{ 29911.1Skamil const int exitval = 5; 29921.1Skamil const int exitval2 = 15; 29931.1Skamil const int sigval = SIGSTOP; 29941.31Skamil pid_t child, child2 = 0, wpid; 29951.1Skamil#if defined(TWAIT_HAVE_STATUS) 29961.1Skamil int status; 29971.1Skamil#endif 29981.1Skamil ptrace_state_t state; 29991.1Skamil const int slen = sizeof(state); 30001.1Skamil ptrace_event_t event; 30011.1Skamil const int elen = sizeof(event); 30021.1Skamil 30031.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 30041.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 30051.1Skamil if (child == 0) { 30061.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 30071.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 30081.1Skamil 30091.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 30101.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 30111.1Skamil 30121.30Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 30131.1Skamil 30141.1Skamil if (child2 == 0) 30151.1Skamil _exit(exitval2); 30161.1Skamil 30171.1Skamil FORKEE_REQUIRE_SUCCESS 30181.1Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 30191.1Skamil 30201.1Skamil forkee_status_exited(status, exitval2); 30211.1Skamil 30221.13Schristos DPRINTF("Before exiting of the child process\n"); 30231.1Skamil _exit(exitval); 30241.1Skamil } 30251.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 30261.1Skamil 30271.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 30281.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 30291.1Skamil 30301.1Skamil validate_status_stopped(status, sigval); 30311.1Skamil 30321.30Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 30331.61Skre trackfork ? "|PTRACE_FORK" : "", 30341.61Skre trackvfork ? "|PTRACE_VFORK" : "", 30351.61Skre trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 30361.30Skamil event.pe_set_event = 0; 30371.30Skamil if (trackfork) 30381.30Skamil event.pe_set_event |= PTRACE_FORK; 30391.30Skamil if (trackvfork) 30401.30Skamil event.pe_set_event |= PTRACE_VFORK; 30411.30Skamil if (trackvforkdone) 30421.30Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 30431.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 30441.1Skamil 30451.13Schristos DPRINTF("Before resuming the child process where it left off and " 30461.1Skamil "without signal to be sent\n"); 30471.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 30481.1Skamil 30491.29Skamil#if defined(TWAIT_HAVE_PID) 30501.31Skamil if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) { 30511.29Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 30521.61Skre child); 30531.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 30541.61Skre child); 30551.1Skamil 30561.29Skamil validate_status_stopped(status, SIGTRAP); 30571.1Skamil 30581.61Skre SYSCALL_REQUIRE( 30591.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 30601.31Skamil if (trackfork && fn == fork) { 30611.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 30621.30Skamil PTRACE_FORK); 30631.30Skamil } 30641.31Skamil if (trackvfork && fn == vfork) { 30651.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 30661.30Skamil PTRACE_VFORK); 30671.30Skamil } 30681.29Skamil 30691.29Skamil child2 = state.pe_other_pid; 30701.30Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 30711.29Skamil 30721.29Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 30731.61Skre "%d\n", TWAIT_FNAME, child2, child); 30741.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 30751.29Skamil child2); 30761.1Skamil 30771.29Skamil validate_status_stopped(status, SIGTRAP); 30781.1Skamil 30791.61Skre SYSCALL_REQUIRE( 30801.61Skre ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 30811.31Skamil if (trackfork && fn == fork) { 30821.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 30831.30Skamil PTRACE_FORK); 30841.30Skamil } 30851.31Skamil if (trackvfork && fn == vfork) { 30861.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 30871.30Skamil PTRACE_VFORK); 30881.30Skamil } 30891.30Skamil 30901.29Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 30911.29Skamil 30921.29Skamil DPRINTF("Before resuming the forkee process where it left off " 30931.29Skamil "and without signal to be sent\n"); 30941.61Skre SYSCALL_REQUIRE( 30951.61Skre ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 30961.29Skamil 30971.29Skamil DPRINTF("Before resuming the child process where it left off " 30981.61Skre "and without signal to be sent\n"); 30991.29Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31001.30Skamil } 31011.30Skamil#endif 31021.30Skamil 31031.31Skamil if (trackvforkdone && fn == vfork) { 31041.30Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 31051.61Skre child); 31061.61Skre TWAIT_REQUIRE_SUCCESS( 31071.61Skre wpid = TWAIT_GENERIC(child, &status, 0), child); 31081.30Skamil 31091.30Skamil validate_status_stopped(status, SIGTRAP); 31101.30Skamil 31111.61Skre SYSCALL_REQUIRE( 31121.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 31131.30Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 31141.30Skamil 31151.30Skamil child2 = state.pe_other_pid; 31161.30Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 31171.61Skre child2); 31181.30Skamil 31191.30Skamil DPRINTF("Before resuming the child process where it left off " 31201.61Skre "and without signal to be sent\n"); 31211.30Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31221.30Skamil } 31231.29Skamil 31241.30Skamil#if defined(TWAIT_HAVE_PID) 31251.31Skamil if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) { 31261.29Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 31271.61Skre "\n", TWAIT_FNAME); 31281.61Skre TWAIT_REQUIRE_SUCCESS( 31291.61Skre wpid = TWAIT_GENERIC(child2, &status, 0), child2); 31301.29Skamil 31311.29Skamil validate_status_exited(status, exitval2); 31321.29Skamil 31331.29Skamil DPRINTF("Before calling %s() for the forkee - expected no " 31341.61Skre "process\n", TWAIT_FNAME); 31351.29Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 31361.29Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 31371.29Skamil } 31381.29Skamil#endif 31391.1Skamil 31401.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 31411.1Skamil "SIGCHLD\n", TWAIT_FNAME); 31421.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31431.1Skamil 31441.1Skamil validate_status_stopped(status, SIGCHLD); 31451.1Skamil 31461.13Schristos DPRINTF("Before resuming the child process where it left off and " 31471.1Skamil "without signal to be sent\n"); 31481.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31491.1Skamil 31501.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 31511.1Skamil TWAIT_FNAME); 31521.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31531.1Skamil 31541.1Skamil validate_status_exited(status, exitval); 31551.1Skamil 31561.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 31571.1Skamil TWAIT_FNAME); 31581.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 31591.1Skamil} 31601.28Skamil 31611.105Skamil#define FORK_TEST(name,fun,tfork,tvfork,tvforkdone) \ 31621.61SkreATF_TC(name); \ 31631.61SkreATF_TC_HEAD(name, tc) \ 31641.61Skre{ \ 31651.105Skamil atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) " \ 31661.105Skamil "called with 0%s%s%s in EVENT_MASK", \ 31671.105Skamil tfork ? "|PTRACE_FORK" : "", \ 31681.105Skamil tvfork ? "|PTRACE_VFORK" : "", \ 31691.105Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 31701.61Skre} \ 31711.61Skre \ 31721.61SkreATF_TC_BODY(name, tc) \ 31731.61Skre{ \ 31741.61Skre \ 31751.105Skamil fork_body(fun, tfork, tvfork, tvforkdone); \ 31761.32Skamil} 31771.32Skamil 31781.105SkamilFORK_TEST(fork1, fork, false, false, false) 31791.31Skamil#if defined(TWAIT_HAVE_PID) 31801.105SkamilFORK_TEST(fork2, fork, true, false, false) 31811.105SkamilFORK_TEST(fork3, fork, false, true, false) 31821.105SkamilFORK_TEST(fork4, fork, true, true, false) 31831.31Skamil#endif 31841.105SkamilFORK_TEST(fork5, fork, false, false, true) 31851.31Skamil#if defined(TWAIT_HAVE_PID) 31861.105SkamilFORK_TEST(fork6, fork, true, false, true) 31871.105SkamilFORK_TEST(fork7, fork, false, true, true) 31881.105SkamilFORK_TEST(fork8, fork, true, true, true) 31891.31Skamil#endif 31901.1Skamil 31911.110Skamil#if TEST_VFORK_ENABLED 31921.105SkamilFORK_TEST(vfork1, vfork, false, false, false) 31931.31Skamil#if defined(TWAIT_HAVE_PID) 31941.105SkamilFORK_TEST(vfork2, vfork, true, false, false) 31951.105SkamilFORK_TEST(vfork3, vfork, false, true, false) 31961.105SkamilFORK_TEST(vfork4, vfork, true, true, false) 31971.31Skamil#endif 31981.105SkamilFORK_TEST(vfork5, vfork, false, false, true) 31991.31Skamil#if defined(TWAIT_HAVE_PID) 32001.105SkamilFORK_TEST(vfork6, vfork, true, false, true) 32011.105SkamilFORK_TEST(vfork7, vfork, false, true, true) 32021.105SkamilFORK_TEST(vfork8, vfork, true, true, true) 32031.31Skamil#endif 32041.110Skamil#endif 32051.31Skamil 32061.54Skamil/// ---------------------------------------------------------------------------- 32071.31Skamil 32081.116Skamil#if defined(TWAIT_HAVE_PID) 32091.116Skamilstatic void 32101.116Skamilfork_detach_forker_body(bool detachfork, bool detachvfork, 32111.116Skamil bool detachvforkdone, bool kill_process) 32121.116Skamil{ 32131.116Skamil const int exitval = 5; 32141.116Skamil const int exitval2 = 15; 32151.116Skamil const int sigval = SIGSTOP; 32161.116Skamil pid_t child, child2 = 0, wpid; 32171.116Skamil#if defined(TWAIT_HAVE_STATUS) 32181.116Skamil int status; 32191.116Skamil#endif 32201.116Skamil ptrace_state_t state; 32211.116Skamil const int slen = sizeof(state); 32221.116Skamil ptrace_event_t event; 32231.116Skamil const int elen = sizeof(event); 32241.116Skamil 32251.116Skamil pid_t (*fn)(void); 32261.116Skamil int op; 32271.116Skamil 32281.116Skamil ATF_REQUIRE((detachfork && !detachvfork && !detachvforkdone) || 32291.116Skamil (!detachfork && detachvfork && !detachvforkdone) || 32301.116Skamil (!detachfork && !detachvfork && detachvforkdone)); 32311.116Skamil 32321.116Skamil if (detachfork) 32331.116Skamil fn = fork; 32341.116Skamil else 32351.116Skamil fn = vfork; 32361.116Skamil 32371.116Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 32381.116Skamil SYSCALL_REQUIRE((child = fork()) != -1); 32391.116Skamil if (child == 0) { 32401.116Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 32411.116Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 32421.116Skamil 32431.116Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 32441.116Skamil FORKEE_ASSERT(raise(sigval) == 0); 32451.116Skamil 32461.116Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 32471.116Skamil 32481.116Skamil if (child2 == 0) 32491.116Skamil _exit(exitval2); 32501.116Skamil 32511.116Skamil FORKEE_REQUIRE_SUCCESS 32521.116Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 32531.116Skamil 32541.116Skamil forkee_status_exited(status, exitval2); 32551.116Skamil 32561.116Skamil DPRINTF("Before exiting of the child process\n"); 32571.116Skamil _exit(exitval); 32581.116Skamil } 32591.116Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 32601.116Skamil 32611.116Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 32621.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 32631.116Skamil 32641.116Skamil validate_status_stopped(status, sigval); 32651.116Skamil 32661.116Skamil DPRINTF("Set EVENT_MASK for the child %d\n", child); 32671.116Skamil event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE; 32681.116Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 32691.116Skamil 32701.116Skamil DPRINTF("Before resuming the child process where it left off and " 32711.116Skamil "without signal to be sent\n"); 32721.116Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 32731.116Skamil 32741.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, child); 32751.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 32761.116Skamil 32771.116Skamil validate_status_stopped(status, SIGTRAP); 32781.116Skamil 32791.116Skamil SYSCALL_REQUIRE( 32801.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 32811.116Skamil op = (fn == fork) ? PTRACE_FORK : PTRACE_VFORK; 32821.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 32831.116Skamil 32841.116Skamil child2 = state.pe_other_pid; 32851.116Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 32861.116Skamil 32871.116Skamil if (detachfork || detachvfork) 32881.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 32891.116Skamil else 32901.116Skamil op = PT_CONTINUE; 32911.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 32921.116Skamil 32931.116Skamil DPRINTF("Before calling %s() for the forkee %d of the child %d\n", 32941.116Skamil TWAIT_FNAME, child2, child); 32951.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 32961.116Skamil 32971.116Skamil validate_status_stopped(status, SIGTRAP); 32981.116Skamil 32991.116Skamil SYSCALL_REQUIRE( 33001.116Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 33011.116Skamil op = (fn == fork) ? PTRACE_FORK : PTRACE_VFORK; 33021.116Skamil ATF_REQUIRE_EQ(state.pe_report_event & op, op); 33031.116Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 33041.116Skamil 33051.116Skamil DPRINTF("Before resuming the forkee process where it left off " 33061.116Skamil "and without signal to be sent\n"); 33071.116Skamil SYSCALL_REQUIRE( 33081.116Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 33091.116Skamil 33101.116Skamil if (detachvforkdone && fn == vfork) { 33111.116Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 33121.116Skamil child); 33131.116Skamil TWAIT_REQUIRE_SUCCESS( 33141.116Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 33151.116Skamil 33161.116Skamil validate_status_stopped(status, SIGTRAP); 33171.116Skamil 33181.116Skamil SYSCALL_REQUIRE( 33191.116Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 33201.116Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 33211.116Skamil 33221.116Skamil child2 = state.pe_other_pid; 33231.116Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 33241.116Skamil child2); 33251.116Skamil 33261.116Skamil op = kill_process ? PT_KILL : PT_DETACH; 33271.116Skamil DPRINTF("Before resuming the child process where it left off " 33281.116Skamil "and without signal to be sent\n"); 33291.116Skamil SYSCALL_REQUIRE(ptrace(op, child, (void *)1, 0) != -1); 33301.116Skamil } 33311.116Skamil 33321.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 33331.116Skamil TWAIT_FNAME); 33341.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), child2); 33351.116Skamil 33361.116Skamil validate_status_exited(status, exitval2); 33371.116Skamil 33381.116Skamil DPRINTF("Before calling %s() for the forkee - expected no process\n", 33391.116Skamil TWAIT_FNAME); 33401.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child2, &status, 0)); 33411.116Skamil 33421.116Skamil DPRINTF("Before calling %s() for the forkee - expected exited\n", 33431.116Skamil TWAIT_FNAME); 33441.116Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33451.116Skamil 33461.116Skamil if (kill_process) { 33471.116Skamil validate_status_signaled(status, SIGKILL, 0); 33481.116Skamil } else { 33491.116Skamil validate_status_exited(status, exitval); 33501.116Skamil } 33511.116Skamil 33521.116Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 33531.116Skamil TWAIT_FNAME); 33541.116Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 33551.116Skamil} 33561.116Skamil 33571.116Skamil#define FORK_DETACH_FORKER(name,detfork,detvfork,detvforkdone,kprocess) \ 33581.116SkamilATF_TC(name); \ 33591.116SkamilATF_TC_HEAD(name, tc) \ 33601.116Skamil{ \ 33611.116Skamil atf_tc_set_md_var(tc, "descr", "Verify %s %s%s%s", \ 33621.116Skamil kprocess ? "killed" : "detached", \ 33631.116Skamil detfork ? "forker" : "", \ 33641.116Skamil detvfork ? "vforker" : "", \ 33651.116Skamil detvforkdone ? "vforker done" : ""); \ 33661.116Skamil} \ 33671.116Skamil \ 33681.116SkamilATF_TC_BODY(name, tc) \ 33691.116Skamil{ \ 33701.116Skamil \ 33711.116Skamil fork_detach_forker_body(detfork, detvfork, detvforkdone, \ 33721.116Skamil kprocess); \ 33731.116Skamil} 33741.116Skamil 33751.116SkamilFORK_DETACH_FORKER(fork_detach_forker, true, false, false, false) 33761.116Skamil#if TEST_VFORK_ENABLED 33771.116SkamilFORK_DETACH_FORKER(vfork_detach_vforker, false, true, false, false) 33781.116SkamilFORK_DETACH_FORKER(vfork_detach_vforkerdone, false, false, true, false) 33791.116Skamil#endif 33801.116SkamilFORK_DETACH_FORKER(fork_kill_forker, true, false, false, true) 33811.116Skamil#if TEST_VFORK_ENABLED 33821.116SkamilFORK_DETACH_FORKER(vfork_kill_vforker, false, true, false, true) 33831.116SkamilFORK_DETACH_FORKER(vfork_kill_vforkerdone, false, false, true, true) 33841.116Skamil#endif 33851.116Skamil#endif 33861.116Skamil 33871.116Skamil/// ---------------------------------------------------------------------------- 33881.116Skamil 33891.110Skamil#if TEST_VFORK_ENABLED 33901.108Skamilstatic void 33911.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void)) 33921.108Skamil{ 33931.108Skamil const int exitval = 5; 33941.108Skamil const int exitval2 = 15; 33951.108Skamil pid_t child, child2 = 0, wpid; 33961.108Skamil#if defined(TWAIT_HAVE_STATUS) 33971.108Skamil int status; 33981.108Skamil#endif 33991.108Skamil 34001.108Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 34011.108Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 34021.108Skamil if (child == 0) { 34031.108Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 34041.108Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 34051.108Skamil 34061.108Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 34071.108Skamil 34081.108Skamil if (child2 == 0) 34091.108Skamil _exit(exitval2); 34101.108Skamil 34111.108Skamil FORKEE_REQUIRE_SUCCESS 34121.108Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 34131.108Skamil 34141.108Skamil forkee_status_exited(status, exitval2); 34151.108Skamil 34161.108Skamil DPRINTF("Before exiting of the child process\n"); 34171.108Skamil _exit(exitval); 34181.108Skamil } 34191.108Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 34201.108Skamil 34211.108Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 34221.108Skamil TWAIT_FNAME); 34231.108Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 34241.108Skamil 34251.108Skamil validate_status_exited(status, exitval); 34261.108Skamil 34271.108Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 34281.108Skamil TWAIT_FNAME); 34291.108Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 34301.108Skamil} 34311.108Skamil 34321.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun) \ 34331.108SkamilATF_TC(name); \ 34341.108SkamilATF_TC_HEAD(name, tc) \ 34351.108Skamil{ \ 34361.108Skamil atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) " \ 34371.108Skamil "called from vfork(2)ed child"); \ 34381.108Skamil} \ 34391.108Skamil \ 34401.108SkamilATF_TC_BODY(name, tc) \ 34411.108Skamil{ \ 34421.108Skamil \ 34431.108Skamil traceme_vfork_fork_body(fun); \ 34441.108Skamil} 34451.108Skamil 34461.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork) 34471.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork) 34481.110Skamil#endif 34491.108Skamil 34501.108Skamil/// ---------------------------------------------------------------------------- 34511.108Skamil 34521.54Skamilenum bytes_transfer_type { 34531.54Skamil BYTES_TRANSFER_DATA, 34541.54Skamil BYTES_TRANSFER_DATAIO, 34551.54Skamil BYTES_TRANSFER_TEXT, 34561.54Skamil BYTES_TRANSFER_TEXTIO, 34571.54Skamil BYTES_TRANSFER_AUXV 34581.54Skamil}; 34591.31Skamil 34601.54Skamilstatic int __used 34611.54Skamilbytes_transfer_dummy(int a, int b, int c, int d) 34621.54Skamil{ 34631.54Skamil int e, f, g, h; 34641.1Skamil 34651.54Skamil a *= 4; 34661.54Skamil b += 3; 34671.54Skamil c -= 2; 34681.54Skamil d /= 1; 34691.1Skamil 34701.54Skamil e = strtol("10", NULL, 10); 34711.54Skamil f = strtol("20", NULL, 10); 34721.54Skamil g = strtol("30", NULL, 10); 34731.54Skamil h = strtol("40", NULL, 10); 34741.1Skamil 34751.54Skamil return (a + b * c - d) + (e * f - g / h); 34761.1Skamil} 34771.1Skamil 34781.54Skamilstatic void 34791.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type) 34801.1Skamil{ 34811.1Skamil const int exitval = 5; 34821.1Skamil const int sigval = SIGSTOP; 34831.1Skamil pid_t child, wpid; 34841.54Skamil bool skip = false; 34851.1Skamil 34861.54Skamil int lookup_me = 0; 34871.54Skamil uint8_t lookup_me8 = 0; 34881.54Skamil uint16_t lookup_me16 = 0; 34891.54Skamil uint32_t lookup_me32 = 0; 34901.54Skamil uint64_t lookup_me64 = 0; 34911.1Skamil 34921.54Skamil int magic = 0x13579246; 34931.54Skamil uint8_t magic8 = 0xab; 34941.54Skamil uint16_t magic16 = 0x1234; 34951.54Skamil uint32_t magic32 = 0x98765432; 34961.54Skamil uint64_t magic64 = 0xabcdef0123456789; 34971.1Skamil 34981.54Skamil struct ptrace_io_desc io; 34991.1Skamil#if defined(TWAIT_HAVE_STATUS) 35001.1Skamil int status; 35011.1Skamil#endif 35021.60Skre /* 513 is just enough, for the purposes of ATF it's good enough */ 35031.60Skre AuxInfo ai[513], *aip; 35041.55Schristos 35051.55Schristos ATF_REQUIRE(size < sizeof(ai)); 35061.1Skamil 35071.54Skamil /* Prepare variables for .TEXT transfers */ 35081.54Skamil switch (type) { 35091.54Skamil case BYTES_TRANSFER_TEXT: 35101.54Skamil memcpy(&magic, bytes_transfer_dummy, sizeof(magic)); 35111.54Skamil break; 35121.54Skamil case BYTES_TRANSFER_TEXTIO: 35131.54Skamil switch (size) { 35141.54Skamil case 8: 35151.54Skamil memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8)); 35161.54Skamil break; 35171.54Skamil case 16: 35181.54Skamil memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16)); 35191.54Skamil break; 35201.54Skamil case 32: 35211.54Skamil memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32)); 35221.54Skamil break; 35231.54Skamil case 64: 35241.54Skamil memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64)); 35251.54Skamil break; 35261.54Skamil } 35271.54Skamil break; 35281.54Skamil default: 35291.54Skamil break; 35301.54Skamil } 35311.1Skamil 35321.54Skamil /* Prepare variables for PIOD and AUXV transfers */ 35331.54Skamil switch (type) { 35341.54Skamil case BYTES_TRANSFER_TEXTIO: 35351.54Skamil case BYTES_TRANSFER_DATAIO: 35361.54Skamil io.piod_op = operation; 35371.54Skamil switch (size) { 35381.54Skamil case 8: 35391.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 35401.54Skamil (void *)bytes_transfer_dummy : 35411.54Skamil &lookup_me8; 35421.54Skamil io.piod_addr = &lookup_me8; 35431.54Skamil io.piod_len = sizeof(lookup_me8); 35441.54Skamil break; 35451.54Skamil case 16: 35461.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 35471.54Skamil (void *)bytes_transfer_dummy : 35481.54Skamil &lookup_me16; 35491.54Skamil io.piod_addr = &lookup_me16; 35501.54Skamil io.piod_len = sizeof(lookup_me16); 35511.54Skamil break; 35521.54Skamil case 32: 35531.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 35541.54Skamil (void *)bytes_transfer_dummy : 35551.54Skamil &lookup_me32; 35561.54Skamil io.piod_addr = &lookup_me32; 35571.54Skamil io.piod_len = sizeof(lookup_me32); 35581.54Skamil break; 35591.54Skamil case 64: 35601.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 35611.54Skamil (void *)bytes_transfer_dummy : 35621.54Skamil &lookup_me64; 35631.54Skamil io.piod_addr = &lookup_me64; 35641.54Skamil io.piod_len = sizeof(lookup_me64); 35651.54Skamil break; 35661.54Skamil default: 35671.54Skamil break; 35681.54Skamil } 35691.54Skamil break; 35701.54Skamil case BYTES_TRANSFER_AUXV: 35711.54Skamil io.piod_op = operation; 35721.54Skamil io.piod_offs = 0; 35731.54Skamil io.piod_addr = ai; 35741.54Skamil io.piod_len = size; 35751.54Skamil break; 35761.54Skamil default: 35771.54Skamil break; 35781.1Skamil } 35791.1Skamil 35801.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 35811.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 35821.1Skamil if (child == 0) { 35831.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 35841.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 35851.1Skamil 35861.54Skamil switch (type) { 35871.54Skamil case BYTES_TRANSFER_DATA: 35881.54Skamil switch (operation) { 35891.54Skamil case PT_READ_D: 35901.54Skamil case PT_READ_I: 35911.54Skamil lookup_me = magic; 35921.54Skamil break; 35931.54Skamil default: 35941.54Skamil break; 35951.54Skamil } 35961.54Skamil break; 35971.54Skamil case BYTES_TRANSFER_DATAIO: 35981.54Skamil switch (operation) { 35991.54Skamil case PIOD_READ_D: 36001.54Skamil case PIOD_READ_I: 36011.54Skamil switch (size) { 36021.54Skamil case 8: 36031.54Skamil lookup_me8 = magic8; 36041.54Skamil break; 36051.54Skamil case 16: 36061.54Skamil lookup_me16 = magic16; 36071.54Skamil break; 36081.54Skamil case 32: 36091.54Skamil lookup_me32 = magic32; 36101.54Skamil break; 36111.54Skamil case 64: 36121.54Skamil lookup_me64 = magic64; 36131.54Skamil break; 36141.54Skamil default: 36151.54Skamil break; 36161.54Skamil } 36171.54Skamil break; 36181.54Skamil default: 36191.54Skamil break; 36201.54Skamil } 36211.54Skamil default: 36221.54Skamil break; 36231.54Skamil } 36241.54Skamil 36251.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 36261.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 36271.1Skamil 36281.54Skamil /* Handle PIOD and PT separately as operation values overlap */ 36291.54Skamil switch (type) { 36301.54Skamil case BYTES_TRANSFER_DATA: 36311.54Skamil switch (operation) { 36321.54Skamil case PT_WRITE_D: 36331.54Skamil case PT_WRITE_I: 36341.54Skamil FORKEE_ASSERT_EQ(lookup_me, magic); 36351.54Skamil break; 36361.54Skamil default: 36371.54Skamil break; 36381.54Skamil } 36391.54Skamil break; 36401.54Skamil case BYTES_TRANSFER_DATAIO: 36411.54Skamil switch (operation) { 36421.54Skamil case PIOD_WRITE_D: 36431.54Skamil case PIOD_WRITE_I: 36441.54Skamil switch (size) { 36451.54Skamil case 8: 36461.54Skamil FORKEE_ASSERT_EQ(lookup_me8, magic8); 36471.54Skamil break; 36481.54Skamil case 16: 36491.54Skamil FORKEE_ASSERT_EQ(lookup_me16, magic16); 36501.54Skamil break; 36511.54Skamil case 32: 36521.54Skamil FORKEE_ASSERT_EQ(lookup_me32, magic32); 36531.54Skamil break; 36541.54Skamil case 64: 36551.54Skamil FORKEE_ASSERT_EQ(lookup_me64, magic64); 36561.54Skamil break; 36571.54Skamil default: 36581.54Skamil break; 36591.54Skamil } 36601.54Skamil break; 36611.54Skamil default: 36621.54Skamil break; 36631.54Skamil } 36641.54Skamil break; 36651.54Skamil case BYTES_TRANSFER_TEXT: 36661.54Skamil FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy, 36671.54Skamil sizeof(magic)) == 0); 36681.54Skamil break; 36691.54Skamil case BYTES_TRANSFER_TEXTIO: 36701.54Skamil switch (size) { 36711.54Skamil case 8: 36721.54Skamil FORKEE_ASSERT(memcmp(&magic8, 36731.54Skamil bytes_transfer_dummy, 36741.54Skamil sizeof(magic8)) == 0); 36751.54Skamil break; 36761.54Skamil case 16: 36771.54Skamil FORKEE_ASSERT(memcmp(&magic16, 36781.54Skamil bytes_transfer_dummy, 36791.54Skamil sizeof(magic16)) == 0); 36801.54Skamil break; 36811.54Skamil case 32: 36821.54Skamil FORKEE_ASSERT(memcmp(&magic32, 36831.54Skamil bytes_transfer_dummy, 36841.54Skamil sizeof(magic32)) == 0); 36851.54Skamil break; 36861.54Skamil case 64: 36871.54Skamil FORKEE_ASSERT(memcmp(&magic64, 36881.54Skamil bytes_transfer_dummy, 36891.54Skamil sizeof(magic64)) == 0); 36901.54Skamil break; 36911.54Skamil } 36921.54Skamil break; 36931.54Skamil default: 36941.54Skamil break; 36951.54Skamil } 36961.54Skamil 36971.13Schristos DPRINTF("Before exiting of the child process\n"); 36981.1Skamil _exit(exitval); 36991.1Skamil } 37001.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 37011.1Skamil 37021.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 37031.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 37041.1Skamil 37051.1Skamil validate_status_stopped(status, sigval); 37061.1Skamil 37071.54Skamil /* Check PaX MPROTECT */ 37081.54Skamil if (!can_we_write_to_text(child)) { 37091.54Skamil switch (type) { 37101.54Skamil case BYTES_TRANSFER_TEXTIO: 37111.54Skamil switch (operation) { 37121.54Skamil case PIOD_WRITE_D: 37131.54Skamil case PIOD_WRITE_I: 37141.54Skamil skip = true; 37151.54Skamil break; 37161.54Skamil default: 37171.54Skamil break; 37181.54Skamil } 37191.54Skamil break; 37201.54Skamil case BYTES_TRANSFER_TEXT: 37211.54Skamil switch (operation) { 37221.54Skamil case PT_WRITE_D: 37231.54Skamil case PT_WRITE_I: 37241.54Skamil skip = true; 37251.54Skamil break; 37261.54Skamil default: 37271.54Skamil break; 37281.54Skamil } 37291.54Skamil break; 37301.54Skamil default: 37311.54Skamil break; 37321.54Skamil } 37331.54Skamil } 37341.1Skamil 37351.54Skamil /* Bailout cleanly killing the child process */ 37361.54Skamil if (skip) { 37371.54Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1); 37381.54Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 37391.54Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 37401.54Skamil child); 37411.1Skamil 37421.54Skamil validate_status_signaled(status, SIGKILL, 0); 37431.1Skamil 37441.54Skamil atf_tc_skip("PaX MPROTECT setup prevents writes to .text"); 37451.54Skamil } 37461.1Skamil 37471.54Skamil DPRINTF("Calling operation to transfer bytes between child=%d and " 37481.54Skamil "parent=%d\n", child, getpid()); 37491.1Skamil 37501.54Skamil switch (type) { 37511.54Skamil case BYTES_TRANSFER_TEXTIO: 37521.54Skamil case BYTES_TRANSFER_DATAIO: 37531.54Skamil case BYTES_TRANSFER_AUXV: 37541.54Skamil switch (operation) { 37551.54Skamil case PIOD_WRITE_D: 37561.54Skamil case PIOD_WRITE_I: 37571.54Skamil switch (size) { 37581.54Skamil case 8: 37591.54Skamil lookup_me8 = magic8; 37601.54Skamil break; 37611.54Skamil case 16: 37621.54Skamil lookup_me16 = magic16; 37631.54Skamil break; 37641.54Skamil case 32: 37651.54Skamil lookup_me32 = magic32; 37661.54Skamil break; 37671.54Skamil case 64: 37681.54Skamil lookup_me64 = magic64; 37691.54Skamil break; 37701.54Skamil default: 37711.54Skamil break; 37721.54Skamil } 37731.54Skamil break; 37741.54Skamil default: 37751.54Skamil break; 37761.54Skamil } 37771.54Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); 37781.54Skamil switch (operation) { 37791.54Skamil case PIOD_READ_D: 37801.54Skamil case PIOD_READ_I: 37811.54Skamil switch (size) { 37821.54Skamil case 8: 37831.54Skamil ATF_REQUIRE_EQ(lookup_me8, magic8); 37841.54Skamil break; 37851.54Skamil case 16: 37861.54Skamil ATF_REQUIRE_EQ(lookup_me16, magic16); 37871.54Skamil break; 37881.54Skamil case 32: 37891.54Skamil ATF_REQUIRE_EQ(lookup_me32, magic32); 37901.54Skamil break; 37911.54Skamil case 64: 37921.54Skamil ATF_REQUIRE_EQ(lookup_me64, magic64); 37931.54Skamil break; 37941.54Skamil default: 37951.54Skamil break; 37961.54Skamil } 37971.54Skamil break; 37981.54Skamil case PIOD_READ_AUXV: 37991.54Skamil DPRINTF("Asserting that AUXV length (%zu) is > 0\n", 38001.54Skamil io.piod_len); 38011.54Skamil ATF_REQUIRE(io.piod_len > 0); 38021.54Skamil for (aip = ai; aip->a_type != AT_NULL; aip++) 38031.54Skamil DPRINTF("a_type=%#llx a_v=%#llx\n", 38041.54Skamil (long long int)aip->a_type, 38051.54Skamil (long long int)aip->a_v); 38061.54Skamil break; 38071.54Skamil default: 38081.54Skamil break; 38091.54Skamil } 38101.54Skamil break; 38111.54Skamil case BYTES_TRANSFER_TEXT: 38121.54Skamil switch (operation) { 38131.54Skamil case PT_READ_D: 38141.54Skamil case PT_READ_I: 38151.54Skamil errno = 0; 38161.54Skamil lookup_me = ptrace(operation, child, 38171.54Skamil bytes_transfer_dummy, 0); 38181.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 38191.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 38201.54Skamil break; 38211.54Skamil case PT_WRITE_D: 38221.54Skamil case PT_WRITE_I: 38231.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, 38241.54Skamil bytes_transfer_dummy, magic) 38251.54Skamil != -1); 38261.54Skamil break; 38271.54Skamil default: 38281.54Skamil break; 38291.54Skamil } 38301.54Skamil break; 38311.54Skamil case BYTES_TRANSFER_DATA: 38321.54Skamil switch (operation) { 38331.54Skamil case PT_READ_D: 38341.54Skamil case PT_READ_I: 38351.54Skamil errno = 0; 38361.54Skamil lookup_me = ptrace(operation, child, &lookup_me, 0); 38371.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 38381.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 38391.54Skamil break; 38401.54Skamil case PT_WRITE_D: 38411.54Skamil case PT_WRITE_I: 38421.54Skamil lookup_me = magic; 38431.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me, 38441.54Skamil magic) != -1); 38451.54Skamil break; 38461.54Skamil default: 38471.54Skamil break; 38481.54Skamil } 38491.54Skamil break; 38501.54Skamil default: 38511.54Skamil break; 38521.54Skamil } 38531.1Skamil 38541.13Schristos DPRINTF("Before resuming the child process where it left off and " 38551.1Skamil "without signal to be sent\n"); 38561.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 38571.1Skamil 38581.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38591.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 38601.1Skamil 38611.1Skamil validate_status_exited(status, exitval); 38621.1Skamil 38631.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38641.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 38651.1Skamil} 38661.1Skamil 38671.61Skre#define BYTES_TRANSFER(test, operation, size, type) \ 38681.61SkreATF_TC(test); \ 38691.61SkreATF_TC_HEAD(test, tc) \ 38701.61Skre{ \ 38711.61Skre atf_tc_set_md_var(tc, "descr", \ 38721.61Skre "Verify bytes transfer operation" #operation " and size " #size \ 38731.61Skre " of type " #type); \ 38741.61Skre} \ 38751.61Skre \ 38761.61SkreATF_TC_BODY(test, tc) \ 38771.61Skre{ \ 38781.61Skre \ 38791.61Skre bytes_transfer(operation, size, BYTES_TRANSFER_##type); \ 38801.1Skamil} 38811.1Skamil 38821.54Skamil// DATA 38831.1Skamil 38841.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO) 38851.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO) 38861.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO) 38871.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO) 38881.54Skamil 38891.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO) 38901.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO) 38911.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO) 38921.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO) 38931.54Skamil 38941.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO) 38951.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO) 38961.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO) 38971.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO) 38981.54Skamil 38991.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO) 39001.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO) 39011.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO) 39021.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO) 39031.54Skamil 39041.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA) 39051.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA) 39061.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA) 39071.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA) 39081.54Skamil 39091.54Skamil// TEXT 39101.54Skamil 39111.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO) 39121.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO) 39131.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO) 39141.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO) 39151.54Skamil 39161.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO) 39171.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO) 39181.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO) 39191.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO) 39201.54Skamil 39211.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO) 39221.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO) 39231.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO) 39241.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO) 39251.54Skamil 39261.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO) 39271.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO) 39281.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO) 39291.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO) 39301.54Skamil 39311.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT) 39321.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT) 39331.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT) 39341.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT) 39351.1Skamil 39361.54Skamil// AUXV 39371.1Skamil 39381.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV) 39391.1Skamil 39401.54Skamil/// ---------------------------------------------------------------------------- 39411.1Skamil 39421.101Skamilstatic void 39431.101Skamilbytes_transfer_alignment(const char *operation) 39441.101Skamil{ 39451.101Skamil const int exitval = 5; 39461.101Skamil const int sigval = SIGSTOP; 39471.101Skamil pid_t child, wpid; 39481.101Skamil#if defined(TWAIT_HAVE_STATUS) 39491.101Skamil int status; 39501.101Skamil#endif 39511.101Skamil char *buffer; 39521.101Skamil int vector; 39531.101Skamil size_t len; 39541.101Skamil size_t i; 39551.101Skamil int op; 39561.101Skamil 39571.101Skamil struct ptrace_io_desc io; 39581.101Skamil struct ptrace_siginfo info; 39591.101Skamil 39601.101Skamil memset(&io, 0, sizeof(io)); 39611.101Skamil memset(&info, 0, sizeof(info)); 39621.101Skamil 39631.101Skamil /* Testing misaligned byte transfer crossing page boundaries */ 39641.101Skamil len = sysconf(_SC_PAGESIZE) * 2; 39651.101Skamil buffer = malloc(len); 39661.101Skamil ATF_REQUIRE(buffer != NULL); 39671.101Skamil 39681.101Skamil /* Initialize the buffer with random data */ 39691.101Skamil for (i = 0; i < len; i++) 39701.101Skamil buffer[i] = i & 0xff; 39711.101Skamil 39721.101Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 39731.101Skamil SYSCALL_REQUIRE((child = fork()) != -1); 39741.101Skamil if (child == 0) { 39751.101Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 39761.101Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 39771.101Skamil 39781.101Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 39791.101Skamil FORKEE_ASSERT(raise(sigval) == 0); 39801.101Skamil 39811.101Skamil DPRINTF("Before exiting of the child process\n"); 39821.101Skamil _exit(exitval); 39831.101Skamil } 39841.101Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 39851.101Skamil 39861.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39871.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 39881.101Skamil 39891.101Skamil validate_status_stopped(status, sigval); 39901.101Skamil 39911.101Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 39921.101Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 39931.101Skamil != -1); 39941.101Skamil 39951.101Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 39961.101Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 39971.101Skamil "si_errno=%#x\n", 39981.101Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 39991.101Skamil info.psi_siginfo.si_errno); 40001.101Skamil 40011.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 40021.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 40031.101Skamil 40041.101Skamil if (strcmp(operation, "PT_READ_I") == 0 || 40051.101Skamil strcmp(operation, "PT_READ_D") == 0) { 40061.101Skamil if (strcmp(operation, "PT_READ_I")) 40071.101Skamil op = PT_READ_I; 40081.101Skamil else 40091.101Skamil op = PT_READ_D; 40101.101Skamil 40111.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 40121.101Skamil errno = 0; 40131.101Skamil vector = ptrace(op, child, buffer + i, 0); 40141.101Skamil ATF_REQUIRE_EQ(errno, 0); 40151.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 40161.101Skamil } 40171.101Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 40181.101Skamil strcmp(operation, "PT_WRITE_D") == 0) { 40191.101Skamil if (strcmp(operation, "PT_WRITE_I")) 40201.101Skamil op = PT_WRITE_I; 40211.101Skamil else 40221.101Skamil op = PT_WRITE_D; 40231.101Skamil 40241.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 40251.101Skamil memcpy(&vector, buffer + i, sizeof(int)); 40261.101Skamil SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector) 40271.101Skamil != -1); 40281.101Skamil } 40291.101Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 40301.101Skamil strcmp(operation, "PIOD_READ_D") == 0) { 40311.101Skamil if (strcmp(operation, "PIOD_READ_I")) 40321.101Skamil op = PIOD_READ_I; 40331.101Skamil else 40341.101Skamil op = PIOD_READ_D; 40351.101Skamil 40361.101Skamil io.piod_op = op; 40371.101Skamil io.piod_addr = &vector; 40381.101Skamil io.piod_len = sizeof(int); 40391.101Skamil 40401.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 40411.101Skamil io.piod_offs = buffer + i; 40421.101Skamil 40431.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 40441.101Skamil != -1); 40451.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 40461.101Skamil } 40471.101Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 40481.101Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 40491.101Skamil if (strcmp(operation, "PIOD_WRITE_I")) 40501.101Skamil op = PIOD_WRITE_I; 40511.101Skamil else 40521.101Skamil op = PIOD_WRITE_D; 40531.101Skamil 40541.101Skamil io.piod_op = op; 40551.101Skamil io.piod_addr = &vector; 40561.101Skamil io.piod_len = sizeof(int); 40571.101Skamil 40581.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 40591.101Skamil io.piod_offs = buffer + i; 40601.101Skamil 40611.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 40621.101Skamil != -1); 40631.101Skamil } 40641.101Skamil } else if (strcmp(operation, "PIOD_READ_AUXV") == 0) { 40651.101Skamil io.piod_op = PIOD_READ_AUXV; 40661.101Skamil io.piod_addr = &vector; 40671.101Skamil io.piod_len = sizeof(int); 40681.101Skamil 40691.101Skamil errno = 0; 40701.101Skamil i = 0; 40711.101Skamil /* Read the whole AUXV vector, it has no clear length */ 40721.120Skamil while (io.piod_len > 0) { 40731.101Skamil io.piod_offs = (void *)(intptr_t)i; 40741.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 40751.120Skamil != -1 || (io.piod_len == 0 && i > 0)); 40761.101Skamil ++i; 40771.101Skamil } 40781.101Skamil } 40791.101Skamil 40801.101Skamil DPRINTF("Before resuming the child process where it left off " 40811.101Skamil "and without signal to be sent\n"); 40821.101Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 40831.101Skamil 40841.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 40851.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 40861.101Skamil child); 40871.101Skamil 40881.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 40891.101Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 40901.101Skamil} 40911.101Skamil 40921.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation) \ 40931.101SkamilATF_TC(test); \ 40941.101SkamilATF_TC_HEAD(test, tc) \ 40951.101Skamil{ \ 40961.101Skamil atf_tc_set_md_var(tc, "descr", \ 40971.101Skamil "Verify bytes transfer for potentially misaligned " \ 40981.101Skamil "operation " operation); \ 40991.101Skamil} \ 41001.101Skamil \ 41011.101SkamilATF_TC_BODY(test, tc) \ 41021.101Skamil{ \ 41031.101Skamil \ 41041.101Skamil bytes_transfer_alignment(operation); \ 41051.101Skamil} 41061.101Skamil 41071.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I") 41081.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D") 41091.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I") 41101.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D") 41111.101Skamil 41121.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I") 41131.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D") 41141.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I") 41151.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D") 41161.101Skamil 41171.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV") 41181.101Skamil 41191.101Skamil/// ---------------------------------------------------------------------------- 41201.101Skamil 41211.115Skamilstatic void 41221.115Skamilbytes_transfer_eof(const char *operation) 41231.115Skamil{ 41241.115Skamil const int exitval = 5; 41251.115Skamil const int sigval = SIGSTOP; 41261.115Skamil pid_t child, wpid; 41271.115Skamil#if defined(TWAIT_HAVE_STATUS) 41281.115Skamil int status; 41291.115Skamil#endif 41301.115Skamil FILE *fp; 41311.115Skamil char *p; 41321.115Skamil int vector; 41331.115Skamil int op; 41341.115Skamil 41351.115Skamil struct ptrace_io_desc io; 41361.115Skamil struct ptrace_siginfo info; 41371.115Skamil 41381.115Skamil memset(&io, 0, sizeof(io)); 41391.115Skamil memset(&info, 0, sizeof(info)); 41401.115Skamil 41411.115Skamil vector = 0; 41421.115Skamil 41431.115Skamil fp = tmpfile(); 41441.115Skamil ATF_REQUIRE(fp != NULL); 41451.115Skamil 41461.115Skamil p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0); 41471.115Skamil ATF_REQUIRE(p != MAP_FAILED); 41481.115Skamil 41491.115Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 41501.115Skamil SYSCALL_REQUIRE((child = fork()) != -1); 41511.115Skamil if (child == 0) { 41521.115Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 41531.115Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 41541.115Skamil 41551.115Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 41561.115Skamil FORKEE_ASSERT(raise(sigval) == 0); 41571.115Skamil 41581.115Skamil DPRINTF("Before exiting of the child process\n"); 41591.115Skamil _exit(exitval); 41601.115Skamil } 41611.115Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 41621.115Skamil 41631.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41641.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 41651.115Skamil 41661.115Skamil validate_status_stopped(status, sigval); 41671.115Skamil 41681.115Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 41691.115Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 41701.115Skamil != -1); 41711.115Skamil 41721.115Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 41731.115Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 41741.115Skamil "si_errno=%#x\n", 41751.115Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 41761.115Skamil info.psi_siginfo.si_errno); 41771.115Skamil 41781.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 41791.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 41801.115Skamil 41811.115Skamil if (strcmp(operation, "PT_READ_I") == 0 || 41821.115Skamil strcmp(operation, "PT_READ_D") == 0) { 41831.115Skamil if (strcmp(operation, "PT_READ_I")) 41841.115Skamil op = PT_READ_I; 41851.115Skamil else 41861.115Skamil op = PT_READ_D; 41871.115Skamil 41881.115Skamil errno = 0; 41891.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, 0) == -1); 41901.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 41911.115Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 41921.115Skamil strcmp(operation, "PT_WRITE_D") == 0) { 41931.115Skamil if (strcmp(operation, "PT_WRITE_I")) 41941.115Skamil op = PT_WRITE_I; 41951.115Skamil else 41961.115Skamil op = PT_WRITE_D; 41971.115Skamil 41981.115Skamil errno = 0; 41991.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, vector) == -1); 42001.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 42011.115Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 42021.115Skamil strcmp(operation, "PIOD_READ_D") == 0) { 42031.115Skamil if (strcmp(operation, "PIOD_READ_I")) 42041.115Skamil op = PIOD_READ_I; 42051.115Skamil else 42061.115Skamil op = PIOD_READ_D; 42071.115Skamil 42081.115Skamil io.piod_op = op; 42091.115Skamil io.piod_addr = &vector; 42101.115Skamil io.piod_len = sizeof(int); 42111.115Skamil io.piod_offs = p; 42121.115Skamil 42131.115Skamil errno = 0; 42141.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 42151.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 42161.115Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 42171.115Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 42181.115Skamil if (strcmp(operation, "PIOD_WRITE_I")) 42191.115Skamil op = PIOD_WRITE_I; 42201.115Skamil else 42211.115Skamil op = PIOD_WRITE_D; 42221.115Skamil 42231.115Skamil io.piod_op = op; 42241.115Skamil io.piod_addr = &vector; 42251.115Skamil io.piod_len = sizeof(int); 42261.115Skamil io.piod_offs = p; 42271.115Skamil 42281.115Skamil errno = 0; 42291.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 42301.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 42311.115Skamil } 42321.115Skamil 42331.115Skamil DPRINTF("Before resuming the child process where it left off " 42341.115Skamil "and without signal to be sent\n"); 42351.115Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 42361.115Skamil 42371.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 42381.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 42391.115Skamil child); 42401.115Skamil 42411.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 42421.115Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 42431.115Skamil} 42441.115Skamil 42451.115Skamil#define BYTES_TRANSFER_EOF(test, operation) \ 42461.115SkamilATF_TC(test); \ 42471.115SkamilATF_TC_HEAD(test, tc) \ 42481.115Skamil{ \ 42491.115Skamil atf_tc_set_md_var(tc, "descr", \ 42501.115Skamil "Verify bytes EOF byte transfer for the " operation \ 42511.115Skamil " operation"); \ 42521.115Skamil} \ 42531.115Skamil \ 42541.115SkamilATF_TC_BODY(test, tc) \ 42551.115Skamil{ \ 42561.115Skamil \ 42571.115Skamil bytes_transfer_eof(operation); \ 42581.115Skamil} 42591.115Skamil 42601.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_i, "PT_READ_I") 42611.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_d, "PT_READ_D") 42621.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_i, "PT_WRITE_I") 42631.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_d, "PT_WRITE_D") 42641.115Skamil 42651.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_i, "PIOD_READ_I") 42661.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_d, "PIOD_READ_D") 42671.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_i, "PIOD_WRITE_I") 42681.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_d, "PIOD_WRITE_D") 42691.115Skamil 42701.115Skamil/// ---------------------------------------------------------------------------- 42711.115Skamil 42721.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS) 42731.72Skamilstatic void 42741.72Skamilaccess_regs(const char *regset, const char *aux) 42751.1Skamil{ 42761.1Skamil const int exitval = 5; 42771.1Skamil const int sigval = SIGSTOP; 42781.1Skamil pid_t child, wpid; 42791.1Skamil#if defined(TWAIT_HAVE_STATUS) 42801.1Skamil int status; 42811.1Skamil#endif 42821.72Skamil#if defined(HAVE_GPREGS) 42831.72Skamil struct reg gpr; 42841.76Sscole register_t rgstr; 42851.1Skamil#endif 42861.72Skamil#if defined(HAVE_FPREGS) 42871.72Skamil struct fpreg fpr; 42881.1Skamil#endif 42891.76Sscole 42901.72Skamil#if !defined(HAVE_GPREGS) 42911.72Skamil if (strcmp(regset, "regs") == 0) 42921.72Skamil atf_tc_fail("Impossible test scenario!"); 42931.1Skamil#endif 42941.1Skamil 42951.72Skamil#if !defined(HAVE_FPREGS) 42961.72Skamil if (strcmp(regset, "fpregs") == 0) 42971.72Skamil atf_tc_fail("Impossible test scenario!"); 42981.1Skamil#endif 42991.1Skamil 43001.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 43011.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 43021.1Skamil if (child == 0) { 43031.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 43041.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 43051.1Skamil 43061.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 43071.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 43081.1Skamil 43091.13Schristos DPRINTF("Before exiting of the child process\n"); 43101.1Skamil _exit(exitval); 43111.1Skamil } 43121.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 43131.1Skamil 43141.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43151.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 43161.1Skamil 43171.1Skamil validate_status_stopped(status, sigval); 43181.1Skamil 43191.1Skamil#if defined(HAVE_GPREGS) 43201.72Skamil if (strcmp(regset, "regs") == 0) { 43211.72Skamil DPRINTF("Call GETREGS for the child process\n"); 43221.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1); 43231.72Skamil 43241.72Skamil if (strcmp(aux, "none") == 0) { 43251.72Skamil DPRINTF("Retrieved registers\n"); 43261.72Skamil } else if (strcmp(aux, "pc") == 0) { 43271.72Skamil rgstr = PTRACE_REG_PC(&gpr); 43281.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 43291.72Skamil } else if (strcmp(aux, "set_pc") == 0) { 43301.72Skamil rgstr = PTRACE_REG_PC(&gpr); 43311.72Skamil PTRACE_REG_SET_PC(&gpr, rgstr); 43321.72Skamil } else if (strcmp(aux, "sp") == 0) { 43331.72Skamil rgstr = PTRACE_REG_SP(&gpr); 43341.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 43351.72Skamil } else if (strcmp(aux, "intrv") == 0) { 43361.72Skamil rgstr = PTRACE_REG_INTRV(&gpr); 43371.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 43381.72Skamil } else if (strcmp(aux, "setregs") == 0) { 43391.72Skamil DPRINTF("Call SETREGS for the child process\n"); 43401.72Skamil SYSCALL_REQUIRE( 43411.72Skamil ptrace(PT_GETREGS, child, &gpr, 0) != -1); 43421.72Skamil } 43431.72Skamil } 43441.1Skamil#endif 43451.1Skamil 43461.72Skamil#if defined(HAVE_FPREGS) 43471.72Skamil if (strcmp(regset, "fpregs") == 0) { 43481.72Skamil DPRINTF("Call GETFPREGS for the child process\n"); 43491.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1); 43501.72Skamil 43511.72Skamil if (strcmp(aux, "getfpregs") == 0) { 43521.72Skamil DPRINTF("Retrieved FP registers\n"); 43531.72Skamil } else if (strcmp(aux, "setfpregs") == 0) { 43541.72Skamil DPRINTF("Call SETFPREGS for the child\n"); 43551.72Skamil SYSCALL_REQUIRE( 43561.72Skamil ptrace(PT_SETFPREGS, child, &fpr, 0) != -1); 43571.72Skamil } 43581.1Skamil } 43591.1Skamil#endif 43601.1Skamil 43611.13Schristos DPRINTF("Before resuming the child process where it left off and " 43621.1Skamil "without signal to be sent\n"); 43631.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 43641.1Skamil 43651.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43661.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 43671.1Skamil 43681.1Skamil validate_status_exited(status, exitval); 43691.1Skamil 43701.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43711.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 43721.1Skamil} 43731.1Skamil 43741.72Skamil#define ACCESS_REGS(test, regset, aux) \ 43751.72SkamilATF_TC(test); \ 43761.72SkamilATF_TC_HEAD(test, tc) \ 43771.72Skamil{ \ 43781.72Skamil atf_tc_set_md_var(tc, "descr", \ 43791.72Skamil "Verify " regset " with auxiliary operation: " aux); \ 43801.72Skamil} \ 43811.72Skamil \ 43821.72SkamilATF_TC_BODY(test, tc) \ 43831.72Skamil{ \ 43841.72Skamil \ 43851.72Skamil access_regs(regset, aux); \ 43861.1Skamil} 43871.1Skamil#endif 43881.1Skamil 43891.72Skamil#if defined(HAVE_GPREGS) 43901.72SkamilACCESS_REGS(access_regs1, "regs", "none") 43911.72SkamilACCESS_REGS(access_regs2, "regs", "pc") 43921.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc") 43931.72SkamilACCESS_REGS(access_regs4, "regs", "sp") 43941.72SkamilACCESS_REGS(access_regs5, "regs", "intrv") 43951.72SkamilACCESS_REGS(access_regs6, "regs", "setregs") 43961.1Skamil#endif 43971.1Skamil#if defined(HAVE_FPREGS) 43981.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs") 43991.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs") 44001.1Skamil#endif 44011.1Skamil 44021.72Skamil/// ---------------------------------------------------------------------------- 44031.1Skamil 44041.1Skamil#if defined(PT_STEP) 44051.1Skamilstatic void 44061.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored) 44071.1Skamil{ 44081.1Skamil const int exitval = 5; 44091.1Skamil const int sigval = SIGSTOP; 44101.1Skamil pid_t child, wpid; 44111.1Skamil#if defined(TWAIT_HAVE_STATUS) 44121.1Skamil int status; 44131.1Skamil#endif 44141.1Skamil int happy; 44151.95Skamil struct sigaction sa; 44161.81Skamil struct ptrace_siginfo info; 44171.95Skamil sigset_t intmask; 44181.95Skamil struct kinfo_proc2 kp; 44191.95Skamil size_t len = sizeof(kp); 44201.95Skamil 44211.95Skamil int name[6]; 44221.95Skamil const size_t namelen = __arraycount(name); 44231.95Skamil ki_sigset_t kp_sigmask; 44241.95Skamil ki_sigset_t kp_sigignore; 44251.1Skamil 44261.1Skamil#if defined(__arm__) 44271.1Skamil /* PT_STEP not supported on arm 32-bit */ 44281.1Skamil atf_tc_expect_fail("PR kern/52119"); 44291.1Skamil#endif 44301.1Skamil 44311.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 44321.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 44331.1Skamil if (child == 0) { 44341.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 44351.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 44361.1Skamil 44371.95Skamil if (masked) { 44381.95Skamil sigemptyset(&intmask); 44391.95Skamil sigaddset(&intmask, SIGTRAP); 44401.95Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 44411.95Skamil } 44421.95Skamil 44431.95Skamil if (ignored) { 44441.95Skamil memset(&sa, 0, sizeof(sa)); 44451.95Skamil sa.sa_handler = SIG_IGN; 44461.95Skamil sigemptyset(&sa.sa_mask); 44471.95Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 44481.95Skamil } 44491.95Skamil 44501.1Skamil happy = check_happy(999); 44511.1Skamil 44521.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 44531.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 44541.1Skamil 44551.1Skamil FORKEE_ASSERT_EQ(happy, check_happy(999)); 44561.1Skamil 44571.13Schristos DPRINTF("Before exiting of the child process\n"); 44581.1Skamil _exit(exitval); 44591.1Skamil } 44601.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 44611.1Skamil 44621.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44631.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44641.1Skamil 44651.1Skamil validate_status_stopped(status, sigval); 44661.1Skamil 44671.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 44681.81Skamil SYSCALL_REQUIRE( 44691.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 44701.81Skamil 44711.81Skamil DPRINTF("Before checking siginfo_t\n"); 44721.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 44731.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 44741.81Skamil 44751.95Skamil name[0] = CTL_KERN, 44761.95Skamil name[1] = KERN_PROC2, 44771.95Skamil name[2] = KERN_PROC_PID; 44781.95Skamil name[3] = child; 44791.95Skamil name[4] = sizeof(kp); 44801.95Skamil name[5] = 1; 44811.95Skamil 44821.95Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 44831.95Skamil 44841.95Skamil if (masked) 44851.95Skamil kp_sigmask = kp.p_sigmask; 44861.95Skamil 44871.95Skamil if (ignored) 44881.95Skamil kp_sigignore = kp.p_sigignore; 44891.95Skamil 44901.1Skamil while (N --> 0) { 44911.2Skamil if (setstep) { 44921.13Schristos DPRINTF("Before resuming the child process where it " 44931.2Skamil "left off and without signal to be sent (use " 44941.9Skamil "PT_SETSTEP and PT_CONTINUE)\n"); 44951.13Schristos SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1); 44961.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) 44971.2Skamil != -1); 44981.2Skamil } else { 44991.13Schristos DPRINTF("Before resuming the child process where it " 45001.2Skamil "left off and without signal to be sent (use " 45011.2Skamil "PT_STEP)\n"); 45021.13Schristos SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) 45031.2Skamil != -1); 45041.2Skamil } 45051.1Skamil 45061.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45071.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 45081.1Skamil child); 45091.1Skamil 45101.1Skamil validate_status_stopped(status, SIGTRAP); 45111.2Skamil 45121.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 45131.81Skamil SYSCALL_REQUIRE( 45141.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 45151.81Skamil 45161.81Skamil DPRINTF("Before checking siginfo_t\n"); 45171.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 45181.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE); 45191.81Skamil 45201.2Skamil if (setstep) { 45211.13Schristos SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1); 45221.2Skamil } 45231.95Skamil 45241.95Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 45251.95Skamil 45261.95Skamil if (masked) { 45271.95Skamil DPRINTF("kp_sigmask=" 45281.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 45291.95Skamil PRIx32 "\n", 45301.95Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 45311.95Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 45321.95Skamil 45331.95Skamil DPRINTF("kp.p_sigmask=" 45341.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 45351.95Skamil PRIx32 "\n", 45361.95Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 45371.95Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 45381.95Skamil 45391.95Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 45401.95Skamil sizeof(kp_sigmask))); 45411.95Skamil } 45421.95Skamil 45431.95Skamil if (ignored) { 45441.95Skamil DPRINTF("kp_sigignore=" 45451.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 45461.95Skamil PRIx32 "\n", 45471.95Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 45481.95Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 45491.95Skamil 45501.95Skamil DPRINTF("kp.p_sigignore=" 45511.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 45521.95Skamil PRIx32 "\n", 45531.95Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 45541.95Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 45551.95Skamil 45561.95Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 45571.95Skamil sizeof(kp_sigignore))); 45581.95Skamil } 45591.1Skamil } 45601.1Skamil 45611.13Schristos DPRINTF("Before resuming the child process where it left off and " 45621.1Skamil "without signal to be sent\n"); 45631.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 45641.1Skamil 45651.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45661.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 45671.1Skamil 45681.1Skamil validate_status_exited(status, exitval); 45691.1Skamil 45701.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45711.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 45721.1Skamil} 45731.1Skamil 45741.73Skamil#define PTRACE_STEP(test, N, setstep) \ 45751.73SkamilATF_TC(test); \ 45761.73SkamilATF_TC_HEAD(test, tc) \ 45771.73Skamil{ \ 45781.73Skamil atf_tc_set_md_var(tc, "descr", \ 45791.74Skamil "Verify " #N " (PT_SETSTEP set to: " #setstep ")"); \ 45801.73Skamil} \ 45811.73Skamil \ 45821.73SkamilATF_TC_BODY(test, tc) \ 45831.73Skamil{ \ 45841.73Skamil \ 45851.95Skamil ptrace_step(N, setstep, false, false); \ 45861.1Skamil} 45871.1Skamil 45881.73SkamilPTRACE_STEP(step1, 1, 0) 45891.73SkamilPTRACE_STEP(step2, 2, 0) 45901.73SkamilPTRACE_STEP(step3, 3, 0) 45911.73SkamilPTRACE_STEP(step4, 4, 0) 45921.73SkamilPTRACE_STEP(setstep1, 1, 1) 45931.73SkamilPTRACE_STEP(setstep2, 2, 1) 45941.73SkamilPTRACE_STEP(setstep3, 3, 1) 45951.73SkamilPTRACE_STEP(setstep4, 4, 1) 45961.95Skamil 45971.95SkamilATF_TC(step_signalmasked); 45981.95SkamilATF_TC_HEAD(step_signalmasked, tc) 45991.95Skamil{ 46001.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP"); 46011.95Skamil} 46021.95Skamil 46031.95SkamilATF_TC_BODY(step_signalmasked, tc) 46041.95Skamil{ 46051.95Skamil 46061.95Skamil ptrace_step(1, 0, true, false); 46071.95Skamil} 46081.95Skamil 46091.95SkamilATF_TC(step_signalignored); 46101.95SkamilATF_TC_HEAD(step_signalignored, tc) 46111.95Skamil{ 46121.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP"); 46131.95Skamil} 46141.95Skamil 46151.95SkamilATF_TC_BODY(step_signalignored, tc) 46161.95Skamil{ 46171.95Skamil 46181.95Skamil ptrace_step(1, 0, false, true); 46191.95Skamil} 46201.1Skamil#endif 46211.1Skamil 46221.73Skamil/// ---------------------------------------------------------------------------- 46231.1Skamil 46241.75Skamilstatic void 46251.75Skamilptrace_kill(const char *type) 46261.1Skamil{ 46271.75Skamil const int sigval = SIGSTOP; 46281.1Skamil pid_t child, wpid; 46291.1Skamil#if defined(TWAIT_HAVE_STATUS) 46301.1Skamil int status; 46311.1Skamil#endif 46321.1Skamil 46331.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 46341.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 46351.1Skamil if (child == 0) { 46361.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 46371.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 46381.1Skamil 46391.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 46401.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 46411.1Skamil 46421.1Skamil /* NOTREACHED */ 46431.1Skamil FORKEE_ASSERTX(0 && 46441.1Skamil "Child should be terminated by a signal from its parent"); 46451.1Skamil } 46461.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 46471.1Skamil 46481.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46491.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 46501.1Skamil 46511.1Skamil validate_status_stopped(status, sigval); 46521.1Skamil 46531.75Skamil DPRINTF("Before killing the child process with %s\n", type); 46541.75Skamil if (strcmp(type, "ptrace(PT_KILL)") == 0) { 46551.75Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1); 46561.75Skamil } else if (strcmp(type, "kill(SIGKILL)") == 0) { 46571.75Skamil kill(child, SIGKILL); 46581.75Skamil } else if (strcmp(type, "killpg(SIGKILL)") == 0) { 46591.75Skamil setpgid(child, 0); 46601.75Skamil killpg(getpgid(child), SIGKILL); 46611.75Skamil } 46621.1Skamil 46631.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46641.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 46651.1Skamil 46661.75Skamil validate_status_signaled(status, SIGKILL, 0); 46671.1Skamil 46681.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46691.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 46701.1Skamil} 46711.1Skamil 46721.75Skamil#define PTRACE_KILL(test, type) \ 46731.75SkamilATF_TC(test); \ 46741.75SkamilATF_TC_HEAD(test, tc) \ 46751.75Skamil{ \ 46761.75Skamil atf_tc_set_md_var(tc, "descr", \ 46771.75Skamil "Verify killing the child with " type); \ 46781.75Skamil} \ 46791.75Skamil \ 46801.75SkamilATF_TC_BODY(test, tc) \ 46811.75Skamil{ \ 46821.75Skamil \ 46831.75Skamil ptrace_kill(type); \ 46841.1Skamil} 46851.1Skamil 46861.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1 46871.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)") 46881.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)") 46891.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)") 46901.1Skamil 46911.75Skamil/// ---------------------------------------------------------------------------- 46921.1Skamil 46931.77Skamilstatic void 46941.77Skamiltraceme_lwpinfo(const int threads) 46951.1Skamil{ 46961.1Skamil const int sigval = SIGSTOP; 46971.77Skamil const int sigval2 = SIGINT; 46981.1Skamil pid_t child, wpid; 46991.1Skamil#if defined(TWAIT_HAVE_STATUS) 47001.1Skamil int status; 47011.1Skamil#endif 47021.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 47031.77Skamil struct ptrace_siginfo info; 47041.77Skamil 47051.77Skamil /* Maximum number of supported threads in this test */ 47061.77Skamil pthread_t t[3]; 47071.77Skamil int n, rv; 47081.77Skamil 47091.77Skamil ATF_REQUIRE((int)__arraycount(t) >= threads); 47101.1Skamil 47111.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 47121.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 47131.1Skamil if (child == 0) { 47141.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 47151.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 47161.1Skamil 47171.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 47181.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 47191.1Skamil 47201.77Skamil for (n = 0; n < threads; n++) { 47211.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 47221.77Skamil FORKEE_ASSERT(rv == 0); 47231.77Skamil } 47241.77Skamil 47251.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval2)); 47261.77Skamil FORKEE_ASSERT(raise(sigval2) == 0); 47271.77Skamil 47281.77Skamil /* NOTREACHED */ 47291.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 47301.1Skamil } 47311.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 47321.1Skamil 47331.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47341.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47351.1Skamil 47361.1Skamil validate_status_stopped(status, sigval); 47371.1Skamil 47381.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 47391.77Skamil SYSCALL_REQUIRE( 47401.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 47411.77Skamil 47421.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 47431.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 47441.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 47451.77Skamil info.psi_siginfo.si_errno); 47461.77Skamil 47471.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 47481.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 47491.77Skamil 47501.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 47511.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 47521.1Skamil 47531.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 47541.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 47551.1Skamil 47561.13Schristos DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n", 47571.77Skamil lwp.pl_lwpid); 47581.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 47591.1Skamil 47601.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 47611.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 47621.1Skamil 47631.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 47641.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 47651.1Skamil 47661.13Schristos DPRINTF("Before resuming the child process where it left off and " 47671.1Skamil "without signal to be sent\n"); 47681.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 47691.1Skamil 47701.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 47711.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47721.1Skamil 47731.77Skamil validate_status_stopped(status, sigval2); 47741.77Skamil 47751.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 47761.77Skamil SYSCALL_REQUIRE( 47771.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 47781.77Skamil 47791.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 47801.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 47811.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 47821.77Skamil info.psi_siginfo.si_errno); 47831.77Skamil 47841.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2); 47851.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 47861.77Skamil 47871.77Skamil memset(&lwp, 0, sizeof(lwp)); 47881.77Skamil 47891.77Skamil for (n = 0; n <= threads; n++) { 47901.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 47911.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 47921.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 47931.77Skamil 47941.77Skamil DPRINTF("Assert that the thread exists\n"); 47951.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 47961.77Skamil 47971.77Skamil DPRINTF("Assert that lwp thread %d received expected event\n", 47981.77Skamil lwp.pl_lwpid); 47991.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ? 48001.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 48011.77Skamil } 48021.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 48031.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 48041.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 48051.77Skamil 48061.77Skamil DPRINTF("Assert that there are no more threads\n"); 48071.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 48081.77Skamil 48091.77Skamil DPRINTF("Before resuming the child process where it left off and " 48101.77Skamil "without signal to be sent\n"); 48111.77Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1); 48121.77Skamil 48131.77Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48141.77Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48151.77Skamil 48161.77Skamil validate_status_signaled(status, SIGKILL, 0); 48171.1Skamil 48181.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48191.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 48201.1Skamil} 48211.1Skamil 48221.77Skamil#define TRACEME_LWPINFO(test, threads) \ 48231.77SkamilATF_TC(test); \ 48241.77SkamilATF_TC_HEAD(test, tc) \ 48251.77Skamil{ \ 48261.77Skamil atf_tc_set_md_var(tc, "descr", \ 48271.77Skamil "Verify LWPINFO with the child with " #threads \ 48281.77Skamil " spawned extra threads"); \ 48291.77Skamil} \ 48301.77Skamil \ 48311.77SkamilATF_TC_BODY(test, tc) \ 48321.77Skamil{ \ 48331.77Skamil \ 48341.77Skamil traceme_lwpinfo(threads); \ 48351.1Skamil} 48361.1Skamil 48371.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0) 48381.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1) 48391.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2) 48401.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3) 48411.77Skamil 48421.77Skamil/// ---------------------------------------------------------------------------- 48431.77Skamil 48441.77Skamil#if defined(TWAIT_HAVE_PID) 48451.77Skamilstatic void 48461.77Skamilattach_lwpinfo(const int threads) 48471.1Skamil{ 48481.77Skamil const int sigval = SIGINT; 48491.1Skamil struct msg_fds parent_tracee, parent_tracer; 48501.1Skamil const int exitval_tracer = 10; 48511.1Skamil pid_t tracee, tracer, wpid; 48521.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 48531.1Skamil#if defined(TWAIT_HAVE_STATUS) 48541.1Skamil int status; 48551.1Skamil#endif 48561.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 48571.77Skamil struct ptrace_siginfo info; 48581.77Skamil 48591.77Skamil /* Maximum number of supported threads in this test */ 48601.77Skamil pthread_t t[3]; 48611.77Skamil int n, rv; 48621.1Skamil 48631.13Schristos DPRINTF("Spawn tracee\n"); 48641.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 48651.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 48661.1Skamil tracee = atf_utils_fork(); 48671.1Skamil if (tracee == 0) { 48681.1Skamil /* Wait for message from the parent */ 48691.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 48701.1Skamil 48711.77Skamil CHILD_FROM_PARENT("spawn threads", parent_tracee, msg); 48721.77Skamil 48731.77Skamil for (n = 0; n < threads; n++) { 48741.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 48751.77Skamil FORKEE_ASSERT(rv == 0); 48761.77Skamil } 48771.77Skamil 48781.77Skamil CHILD_TO_PARENT("tracee exit", parent_tracee, msg); 48791.77Skamil 48801.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 48811.77Skamil FORKEE_ASSERT(raise(sigval) == 0); 48821.77Skamil 48831.77Skamil /* NOTREACHED */ 48841.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 48851.1Skamil } 48861.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 48871.1Skamil 48881.13Schristos DPRINTF("Spawn debugger\n"); 48891.1Skamil tracer = atf_utils_fork(); 48901.1Skamil if (tracer == 0) { 48911.1Skamil /* No IPC to communicate with the child */ 48921.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 48931.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 48941.1Skamil 48951.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 48961.1Skamil FORKEE_REQUIRE_SUCCESS( 48971.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 48981.1Skamil 48991.1Skamil forkee_status_stopped(status, SIGSTOP); 49001.1Skamil 49011.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 49021.77Skamil "tracee"); 49031.77Skamil FORKEE_ASSERT( 49041.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 49051.77Skamil 49061.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 49071.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 49081.77Skamil "si_errno=%#x\n", 49091.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 49101.77Skamil info.psi_siginfo.si_errno); 49111.77Skamil 49121.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 49131.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 49141.77Skamil 49151.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 49161.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 49171.1Skamil != -1); 49181.1Skamil 49191.13Schristos DPRINTF("Assert that there exists a thread\n"); 49201.77Skamil FORKEE_ASSERTX(lwp.pl_lwpid > 0); 49211.1Skamil 49221.13Schristos DPRINTF("Assert that lwp thread %d received event " 49231.77Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 49241.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 49251.1Skamil 49261.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 49271.77Skamil "tracee\n"); 49281.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 49291.1Skamil != -1); 49301.1Skamil 49311.77Skamil DPRINTF("Assert that there are no more lwp threads in " 49321.77Skamil "tracee\n"); 49331.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 49341.1Skamil 49351.1Skamil /* Resume tracee with PT_CONTINUE */ 49361.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 49371.1Skamil 49381.1Skamil /* Inform parent that tracer has attached to tracee */ 49391.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 49401.77Skamil 49411.1Skamil /* Wait for parent */ 49421.1Skamil CHILD_FROM_PARENT("tracer wait", parent_tracer, msg); 49431.1Skamil 49441.77Skamil /* Wait for tracee and assert that it raised a signal */ 49451.77Skamil FORKEE_REQUIRE_SUCCESS( 49461.77Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 49471.77Skamil 49481.77Skamil forkee_status_stopped(status, SIGINT); 49491.77Skamil 49501.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 49511.77Skamil "child"); 49521.77Skamil FORKEE_ASSERT( 49531.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 49541.77Skamil 49551.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 49561.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 49571.77Skamil "si_errno=%#x\n", 49581.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 49591.77Skamil info.psi_siginfo.si_errno); 49601.77Skamil 49611.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 49621.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 49631.77Skamil 49641.77Skamil memset(&lwp, 0, sizeof(lwp)); 49651.77Skamil 49661.77Skamil for (n = 0; n <= threads; n++) { 49671.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 49681.77Skamil "child\n"); 49691.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, 49701.77Skamil sizeof(lwp)) != -1); 49711.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 49721.77Skamil 49731.77Skamil DPRINTF("Assert that the thread exists\n"); 49741.77Skamil FORKEE_ASSERT(lwp.pl_lwpid > 0); 49751.77Skamil 49761.77Skamil DPRINTF("Assert that lwp thread %d received expected " 49771.77Skamil "event\n", lwp.pl_lwpid); 49781.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 49791.77Skamil info.psi_lwpid == lwp.pl_lwpid ? 49801.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 49811.77Skamil } 49821.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 49831.77Skamil "tracee\n"); 49841.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 49851.77Skamil != -1); 49861.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 49871.77Skamil 49881.77Skamil DPRINTF("Assert that there are no more threads\n"); 49891.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 49901.77Skamil 49911.77Skamil DPRINTF("Before resuming the child process where it left off " 49921.77Skamil "and without signal to be sent\n"); 49931.77Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL) 49941.77Skamil != -1); 49951.77Skamil 49961.1Skamil /* Wait for tracee and assert that it exited */ 49971.1Skamil FORKEE_REQUIRE_SUCCESS( 49981.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 49991.1Skamil 50001.77Skamil forkee_status_signaled(status, SIGKILL, 0); 50011.1Skamil 50021.13Schristos DPRINTF("Before exiting of the tracer process\n"); 50031.1Skamil _exit(exitval_tracer); 50041.1Skamil } 50051.1Skamil 50061.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 50071.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 50081.1Skamil 50091.77Skamil DPRINTF("Resume the tracee and spawn threads\n"); 50101.77Skamil PARENT_TO_CHILD("spawn threads", parent_tracee, msg); 50111.77Skamil 50121.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 50131.77Skamil PARENT_FROM_CHILD("tracee exit", parent_tracee, msg); 50141.1Skamil 50151.77Skamil DPRINTF("Resume the tracer and let it detect multiple threads\n"); 50161.1Skamil PARENT_TO_CHILD("tracer wait", parent_tracer, msg); 50171.1Skamil 50181.13Schristos DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n", 50191.1Skamil TWAIT_FNAME); 50201.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 50211.1Skamil tracer); 50221.1Skamil 50231.1Skamil validate_status_exited(status, exitval_tracer); 50241.1Skamil 50251.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 50261.1Skamil TWAIT_FNAME); 50271.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 50281.1Skamil tracee); 50291.1Skamil 50301.77Skamil validate_status_signaled(status, SIGKILL, 0); 50311.1Skamil 50321.1Skamil msg_close(&parent_tracer); 50331.1Skamil msg_close(&parent_tracee); 50341.1Skamil} 50351.77Skamil 50361.77Skamil#define ATTACH_LWPINFO(test, threads) \ 50371.77SkamilATF_TC(test); \ 50381.77SkamilATF_TC_HEAD(test, tc) \ 50391.77Skamil{ \ 50401.77Skamil atf_tc_set_md_var(tc, "descr", \ 50411.77Skamil "Verify LWPINFO with the child with " #threads \ 50421.77Skamil " spawned extra threads (tracer is not the original " \ 50431.77Skamil "parent)"); \ 50441.77Skamil} \ 50451.77Skamil \ 50461.77SkamilATF_TC_BODY(test, tc) \ 50471.77Skamil{ \ 50481.77Skamil \ 50491.77Skamil attach_lwpinfo(threads); \ 50501.77Skamil} 50511.77Skamil 50521.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0) 50531.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1) 50541.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2) 50551.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3) 50561.1Skamil#endif 50571.1Skamil 50581.77Skamil/// ---------------------------------------------------------------------------- 50591.77Skamil 50601.1Skamilstatic void 50611.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught) 50621.1Skamil{ 50631.1Skamil const int exitval = 5; 50641.1Skamil const int sigval = SIGINT; 50651.1Skamil const int sigfaked = SIGTRAP; 50661.1Skamil const int sicodefaked = TRAP_BRKPT; 50671.1Skamil pid_t child, wpid; 50681.1Skamil struct sigaction sa; 50691.1Skamil#if defined(TWAIT_HAVE_STATUS) 50701.1Skamil int status; 50711.1Skamil#endif 50721.1Skamil struct ptrace_siginfo info; 50731.1Skamil memset(&info, 0, sizeof(info)); 50741.1Skamil 50751.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 50761.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 50771.1Skamil if (child == 0) { 50781.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 50791.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 50801.1Skamil 50811.79Skamil sa.sa_sigaction = sah; 50821.1Skamil sa.sa_flags = SA_SIGINFO; 50831.1Skamil sigemptyset(&sa.sa_mask); 50841.1Skamil 50851.79Skamil FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL) 50861.79Skamil != -1); 50871.1Skamil 50881.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 50891.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 50901.1Skamil 50911.79Skamil FORKEE_ASSERT_EQ(*signal_caught, 1); 50921.1Skamil 50931.13Schristos DPRINTF("Before exiting of the child process\n"); 50941.1Skamil _exit(exitval); 50951.1Skamil } 50961.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 50971.1Skamil 50981.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 50991.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 51001.1Skamil 51011.1Skamil validate_status_stopped(status, sigval); 51021.1Skamil 51031.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 51041.61Skre SYSCALL_REQUIRE( 51051.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 51061.1Skamil 51071.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 51081.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 51091.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 51101.1Skamil info.psi_siginfo.si_errno); 51111.1Skamil 51121.79Skamil if (faked) { 51131.79Skamil DPRINTF("Before setting new faked signal to signo=%d " 51141.79Skamil "si_code=%d\n", sigfaked, sicodefaked); 51151.79Skamil info.psi_siginfo.si_signo = sigfaked; 51161.79Skamil info.psi_siginfo.si_code = sicodefaked; 51171.79Skamil } 51181.1Skamil 51191.13Schristos DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n"); 51201.61Skre SYSCALL_REQUIRE( 51211.61Skre ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1); 51221.1Skamil 51231.79Skamil if (faked) { 51241.79Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 51251.79Skamil "child\n"); 51261.79Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 51271.79Skamil sizeof(info)) != -1); 51281.1Skamil 51291.79Skamil DPRINTF("Before checking siginfo_t\n"); 51301.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked); 51311.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked); 51321.79Skamil } 51331.1Skamil 51341.13Schristos DPRINTF("Before resuming the child process where it left off and " 51351.1Skamil "without signal to be sent\n"); 51361.79Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 51371.79Skamil faked ? sigfaked : sigval) != -1); 51381.1Skamil 51391.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51401.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 51411.1Skamil 51421.1Skamil validate_status_exited(status, exitval); 51431.1Skamil 51441.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51451.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 51461.1Skamil} 51471.1Skamil 51481.79Skamil#define PTRACE_SIGINFO(test, faked) \ 51491.79SkamilATF_TC(test); \ 51501.79SkamilATF_TC_HEAD(test, tc) \ 51511.79Skamil{ \ 51521.79Skamil atf_tc_set_md_var(tc, "descr", \ 51531.79Skamil "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls" \ 51541.79Skamil "with%s setting signal to new value", faked ? "" : "out"); \ 51551.79Skamil} \ 51561.79Skamil \ 51571.79Skamilstatic int test##_caught = 0; \ 51581.79Skamil \ 51591.79Skamilstatic void \ 51601.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx) \ 51611.79Skamil{ \ 51621.79Skamil if (faked) { \ 51631.79Skamil FORKEE_ASSERT_EQ(sig, SIGTRAP); \ 51641.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP); \ 51651.79Skamil FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT); \ 51661.79Skamil } else { \ 51671.79Skamil FORKEE_ASSERT_EQ(sig, SIGINT); \ 51681.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGINT); \ 51691.79Skamil FORKEE_ASSERT_EQ(info->si_code, SI_LWP); \ 51701.79Skamil } \ 51711.79Skamil \ 51721.79Skamil ++ test##_caught; \ 51731.79Skamil} \ 51741.79Skamil \ 51751.79SkamilATF_TC_BODY(test, tc) \ 51761.79Skamil{ \ 51771.79Skamil \ 51781.79Skamil ptrace_siginfo(faked, test##_sighandler, & test##_caught); \ 51791.79Skamil} 51801.79Skamil 51811.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false) 51821.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true) 51831.79Skamil 51841.79Skamil/// ---------------------------------------------------------------------------- 51851.79Skamil 51861.97Skamilstatic void 51871.97Skamiltraceme_exec(bool masked, bool ignored) 51881.1Skamil{ 51891.1Skamil const int sigval = SIGTRAP; 51901.1Skamil pid_t child, wpid; 51911.1Skamil#if defined(TWAIT_HAVE_STATUS) 51921.1Skamil int status; 51931.1Skamil#endif 51941.97Skamil struct sigaction sa; 51951.97Skamil struct ptrace_siginfo info; 51961.97Skamil sigset_t intmask; 51971.97Skamil struct kinfo_proc2 kp; 51981.97Skamil size_t len = sizeof(kp); 51991.97Skamil 52001.97Skamil int name[6]; 52011.97Skamil const size_t namelen = __arraycount(name); 52021.97Skamil ki_sigset_t kp_sigmask; 52031.97Skamil ki_sigset_t kp_sigignore; 52041.1Skamil 52051.1Skamil memset(&info, 0, sizeof(info)); 52061.1Skamil 52071.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 52081.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 52091.1Skamil if (child == 0) { 52101.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 52111.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 52121.1Skamil 52131.97Skamil if (masked) { 52141.97Skamil sigemptyset(&intmask); 52151.97Skamil sigaddset(&intmask, sigval); 52161.97Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 52171.97Skamil } 52181.97Skamil 52191.97Skamil if (ignored) { 52201.97Skamil memset(&sa, 0, sizeof(sa)); 52211.97Skamil sa.sa_handler = SIG_IGN; 52221.97Skamil sigemptyset(&sa.sa_mask); 52231.97Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 52241.97Skamil } 52251.97Skamil 52261.13Schristos DPRINTF("Before calling execve(2) from child\n"); 52271.1Skamil execlp("/bin/echo", "/bin/echo", NULL); 52281.1Skamil 52291.1Skamil FORKEE_ASSERT(0 && "Not reached"); 52301.1Skamil } 52311.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 52321.1Skamil 52331.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52341.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52351.1Skamil 52361.1Skamil validate_status_stopped(status, sigval); 52371.1Skamil 52381.97Skamil name[0] = CTL_KERN, 52391.97Skamil name[1] = KERN_PROC2, 52401.97Skamil name[2] = KERN_PROC_PID; 52411.97Skamil name[3] = getpid(); 52421.97Skamil name[4] = sizeof(kp); 52431.97Skamil name[5] = 1; 52441.97Skamil 52451.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 52461.97Skamil 52471.97Skamil if (masked) 52481.97Skamil kp_sigmask = kp.p_sigmask; 52491.97Skamil 52501.97Skamil if (ignored) 52511.97Skamil kp_sigignore = kp.p_sigignore; 52521.97Skamil 52531.97Skamil name[3] = getpid(); 52541.97Skamil 52551.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 52561.97Skamil 52571.97Skamil if (masked) { 52581.97Skamil DPRINTF("kp_sigmask=" 52591.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 52601.97Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 52611.97Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 52621.97Skamil 52631.97Skamil DPRINTF("kp.p_sigmask=" 52641.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 52651.97Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 52661.97Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 52671.97Skamil 52681.97Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 52691.97Skamil sizeof(kp_sigmask))); 52701.97Skamil } 52711.97Skamil 52721.97Skamil if (ignored) { 52731.97Skamil DPRINTF("kp_sigignore=" 52741.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 52751.97Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 52761.97Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 52771.97Skamil 52781.97Skamil DPRINTF("kp.p_sigignore=" 52791.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 52801.97Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 52811.97Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 52821.97Skamil 52831.97Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 52841.97Skamil sizeof(kp_sigignore))); 52851.97Skamil } 52861.97Skamil 52871.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 52881.61Skre SYSCALL_REQUIRE( 52891.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 52901.1Skamil 52911.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 52921.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 52931.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 52941.1Skamil info.psi_siginfo.si_errno); 52951.1Skamil 52961.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 52971.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 52981.1Skamil 52991.13Schristos DPRINTF("Before resuming the child process where it left off and " 53001.1Skamil "without signal to be sent\n"); 53011.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 53021.1Skamil 53031.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53041.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 53051.1Skamil 53061.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53071.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 53081.1Skamil} 53091.1Skamil 53101.97Skamil#define TRACEME_EXEC(test, masked, ignored) \ 53111.97SkamilATF_TC(test); \ 53121.97SkamilATF_TC_HEAD(test, tc) \ 53131.97Skamil{ \ 53141.97Skamil atf_tc_set_md_var(tc, "descr", \ 53151.97Skamil "Detect SIGTRAP TRAP_EXEC from " \ 53161.97Skamil "child%s%s", masked ? " with masked signal" : "", \ 53171.97Skamil masked ? " with ignored signal" : ""); \ 53181.97Skamil} \ 53191.97Skamil \ 53201.97SkamilATF_TC_BODY(test, tc) \ 53211.97Skamil{ \ 53221.97Skamil \ 53231.97Skamil traceme_exec(masked, ignored); \ 53241.97Skamil} 53251.97Skamil 53261.97SkamilTRACEME_EXEC(traceme_exec, false, false) 53271.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false) 53281.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true) 53291.97Skamil 53301.82Skamil/// ---------------------------------------------------------------------------- 53311.82Skamil 53321.83Skamilstatic volatile int done; 53331.1Skamil 53341.83Skamilstatic void * 53351.83Skamiltrace_threads_cb(void *arg __unused) 53361.1Skamil{ 53371.1Skamil 53381.83Skamil done++; 53391.83Skamil 53401.83Skamil while (done < 3) 53411.83Skamil continue; 53421.83Skamil 53431.83Skamil return NULL; 53441.1Skamil} 53451.1Skamil 53461.83Skamilstatic void 53471.83Skamiltrace_threads(bool trace_create, bool trace_exit) 53481.1Skamil{ 53491.1Skamil const int sigval = SIGSTOP; 53501.1Skamil pid_t child, wpid; 53511.1Skamil#if defined(TWAIT_HAVE_STATUS) 53521.1Skamil int status; 53531.1Skamil#endif 53541.1Skamil ptrace_state_t state; 53551.1Skamil const int slen = sizeof(state); 53561.1Skamil ptrace_event_t event; 53571.1Skamil const int elen = sizeof(event); 53581.83Skamil struct ptrace_siginfo info; 53591.83Skamil 53601.83Skamil pthread_t t[3]; 53611.83Skamil int rv; 53621.83Skamil size_t n; 53631.1Skamil lwpid_t lid; 53641.83Skamil 53651.83Skamil /* Track created and exited threads */ 53661.83Skamil bool traced_lwps[__arraycount(t)]; 53671.83Skamil 53681.120Skamil if (trace_create || trace_exit) 53691.119Skamil atf_tc_skip("PR kern/51995"); 53701.1Skamil 53711.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 53721.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 53731.1Skamil if (child == 0) { 53741.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 53751.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 53761.1Skamil 53771.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 53781.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 53791.1Skamil 53801.83Skamil for (n = 0; n < __arraycount(t); n++) { 53811.83Skamil rv = pthread_create(&t[n], NULL, trace_threads_cb, 53821.83Skamil NULL); 53831.83Skamil FORKEE_ASSERT(rv == 0); 53841.83Skamil } 53851.1Skamil 53861.83Skamil for (n = 0; n < __arraycount(t); n++) { 53871.83Skamil rv = pthread_join(t[n], NULL); 53881.83Skamil FORKEE_ASSERT(rv == 0); 53891.83Skamil } 53901.1Skamil 53911.83Skamil /* 53921.83Skamil * There is race between _exit() and pthread_join() detaching 53931.83Skamil * a thread. For simplicity kill the process after detecting 53941.83Skamil * LWP events. 53951.83Skamil */ 53961.83Skamil while (true) 53971.83Skamil continue; 53981.1Skamil 53991.83Skamil FORKEE_ASSERT(0 && "Not reached"); 54001.1Skamil } 54011.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 54021.1Skamil 54031.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54041.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 54051.1Skamil 54061.1Skamil validate_status_stopped(status, sigval); 54071.1Skamil 54081.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 54091.83Skamil SYSCALL_REQUIRE( 54101.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 54111.1Skamil 54121.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 54131.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 54141.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 54151.83Skamil info.psi_siginfo.si_errno); 54161.1Skamil 54171.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 54181.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 54191.1Skamil 54201.83Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 54211.83Skamil memset(&event, 0, sizeof(event)); 54221.83Skamil if (trace_create) 54231.83Skamil event.pe_set_event |= PTRACE_LWP_CREATE; 54241.83Skamil if (trace_exit) 54251.83Skamil event.pe_set_event |= PTRACE_LWP_EXIT; 54261.83Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 54271.1Skamil 54281.13Schristos DPRINTF("Before resuming the child process where it left off and " 54291.1Skamil "without signal to be sent\n"); 54301.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 54311.1Skamil 54321.83Skamil memset(traced_lwps, 0, sizeof(traced_lwps)); 54331.1Skamil 54341.83Skamil for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) { 54351.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 54361.83Skamil "SIGTRAP\n", TWAIT_FNAME); 54371.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 54381.83Skamil child); 54391.1Skamil 54401.83Skamil validate_status_stopped(status, SIGTRAP); 54411.1Skamil 54421.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 54431.83Skamil "child\n"); 54441.83Skamil SYSCALL_REQUIRE( 54451.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 54461.1Skamil 54471.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 54481.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 54491.83Skamil "si_errno=%#x\n", 54501.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 54511.83Skamil info.psi_siginfo.si_errno); 54521.1Skamil 54531.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 54541.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 54551.1Skamil 54561.83Skamil SYSCALL_REQUIRE( 54571.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 54581.1Skamil 54591.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 54601.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 54611.1Skamil 54621.83Skamil lid = state.pe_lwp; 54631.83Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 54641.1Skamil 54651.83Skamil traced_lwps[lid - 1] = true; 54661.1Skamil 54671.83Skamil DPRINTF("Before resuming the child process where it left off " 54681.83Skamil "and without signal to be sent\n"); 54691.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 54701.83Skamil } 54711.1Skamil 54721.83Skamil for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) { 54731.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 54741.83Skamil "SIGTRAP\n", TWAIT_FNAME); 54751.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 54761.83Skamil child); 54771.1Skamil 54781.83Skamil validate_status_stopped(status, SIGTRAP); 54791.1Skamil 54801.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 54811.83Skamil "child\n"); 54821.83Skamil SYSCALL_REQUIRE( 54831.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 54841.1Skamil 54851.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 54861.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 54871.83Skamil "si_errno=%#x\n", 54881.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 54891.83Skamil info.psi_siginfo.si_errno); 54901.1Skamil 54911.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 54921.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 54931.1Skamil 54941.83Skamil SYSCALL_REQUIRE( 54951.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 54961.1Skamil 54971.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 54981.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 54991.1Skamil 55001.83Skamil lid = state.pe_lwp; 55011.83Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 55021.1Skamil 55031.83Skamil if (trace_create) { 55041.83Skamil ATF_REQUIRE(traced_lwps[lid - 1] == true); 55051.83Skamil traced_lwps[lid - 1] = false; 55061.83Skamil } 55071.1Skamil 55081.83Skamil DPRINTF("Before resuming the child process where it left off " 55091.83Skamil "and without signal to be sent\n"); 55101.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 55111.83Skamil } 55121.1Skamil 55131.83Skamil kill(child, SIGKILL); 55141.1Skamil 55151.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 55161.1Skamil TWAIT_FNAME); 55171.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 55181.1Skamil 55191.83Skamil validate_status_signaled(status, SIGKILL, 0); 55201.1Skamil 55211.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 55221.1Skamil TWAIT_FNAME); 55231.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 55241.1Skamil} 55251.1Skamil 55261.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit) \ 55271.83SkamilATF_TC(test); \ 55281.83SkamilATF_TC_HEAD(test, tc) \ 55291.83Skamil{ \ 55301.83Skamil atf_tc_set_md_var(tc, "descr", \ 55311.83Skamil "Verify spawning threads with%s tracing LWP create and" \ 55321.83Skamil "with%s tracing LWP exit", trace_create ? "" : "out", \ 55331.83Skamil trace_exit ? "" : "out"); \ 55341.83Skamil} \ 55351.83Skamil \ 55361.83SkamilATF_TC_BODY(test, tc) \ 55371.83Skamil{ \ 55381.83Skamil \ 55391.83Skamil trace_threads(trace_create, trace_exit); \ 55401.83Skamil} 55411.83Skamil 55421.119SkamilTRACE_THREADS(trace_thread_nolwpevents, false, false) 55431.119SkamilTRACE_THREADS(trace_thread_lwpexit, false, true) 55441.119SkamilTRACE_THREADS(trace_thread_lwpcreate, true, false) 55451.119SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true) 55461.83Skamil 55471.83Skamil/// ---------------------------------------------------------------------------- 55481.83Skamil 55491.84SkamilATF_TC(signal_mask_unrelated); 55501.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc) 55511.1Skamil{ 55521.1Skamil atf_tc_set_md_var(tc, "descr", 55531.1Skamil "Verify that masking single unrelated signal does not stop tracer " 55541.1Skamil "from catching other signals"); 55551.1Skamil} 55561.1Skamil 55571.84SkamilATF_TC_BODY(signal_mask_unrelated, tc) 55581.1Skamil{ 55591.1Skamil const int exitval = 5; 55601.1Skamil const int sigval = SIGSTOP; 55611.1Skamil const int sigmasked = SIGTRAP; 55621.1Skamil const int signotmasked = SIGINT; 55631.1Skamil pid_t child, wpid; 55641.1Skamil#if defined(TWAIT_HAVE_STATUS) 55651.1Skamil int status; 55661.1Skamil#endif 55671.1Skamil sigset_t intmask; 55681.1Skamil 55691.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 55701.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 55711.1Skamil if (child == 0) { 55721.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 55731.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 55741.1Skamil 55751.1Skamil sigemptyset(&intmask); 55761.1Skamil sigaddset(&intmask, sigmasked); 55771.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 55781.1Skamil 55791.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 55801.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 55811.1Skamil 55821.13Schristos DPRINTF("Before raising %s from child\n", 55831.1Skamil strsignal(signotmasked)); 55841.1Skamil FORKEE_ASSERT(raise(signotmasked) == 0); 55851.1Skamil 55861.13Schristos DPRINTF("Before exiting of the child process\n"); 55871.1Skamil _exit(exitval); 55881.1Skamil } 55891.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 55901.1Skamil 55911.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 55921.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 55931.1Skamil 55941.1Skamil validate_status_stopped(status, sigval); 55951.1Skamil 55961.13Schristos DPRINTF("Before resuming the child process where it left off and " 55971.1Skamil "without signal to be sent\n"); 55981.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 55991.1Skamil 56001.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56011.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56021.1Skamil 56031.1Skamil validate_status_stopped(status, signotmasked); 56041.1Skamil 56051.13Schristos DPRINTF("Before resuming the child process where it left off and " 56061.1Skamil "without signal to be sent\n"); 56071.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56081.1Skamil 56091.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56101.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56111.1Skamil 56121.1Skamil validate_status_exited(status, exitval); 56131.1Skamil 56141.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56151.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 56161.1Skamil} 56171.1Skamil 56181.84Skamil/// ---------------------------------------------------------------------------- 56191.84Skamil 56201.1Skamil#if defined(TWAIT_HAVE_PID) 56211.99Skamilstatic void 56221.99Skamilfork2_body(bool trackfork, bool trackvfork, bool trackvforkdone, bool masked, 56231.99Skamil bool ignored) 56241.1Skamil{ 56251.1Skamil const int exitval = 5; 56261.1Skamil const int exitval2 = 15; 56271.1Skamil const int sigval = SIGSTOP; 56281.99Skamil pid_t child, child2 = 0, wpid; 56291.1Skamil#if defined(TWAIT_HAVE_STATUS) 56301.1Skamil int status; 56311.1Skamil#endif 56321.1Skamil ptrace_state_t state; 56331.1Skamil const int slen = sizeof(state); 56341.1Skamil ptrace_event_t event; 56351.1Skamil const int elen = sizeof(event); 56361.99Skamil pid_t (*fn)(void); 56371.99Skamil struct sigaction sa; 56381.99Skamil struct ptrace_siginfo info; 56391.99Skamil sigset_t intmask; 56401.99Skamil struct kinfo_proc2 kp; 56411.99Skamil size_t len = sizeof(kp); 56421.99Skamil 56431.99Skamil int name[6]; 56441.99Skamil const size_t namelen = __arraycount(name); 56451.99Skamil ki_sigset_t kp_sigmask; 56461.99Skamil ki_sigset_t kp_sigignore; 56471.1Skamil 56481.99Skamil if (trackfork) 56491.99Skamil fn = fork; 56501.99Skamil if (trackvfork || trackvforkdone) 56511.99Skamil fn = vfork; 56521.14Schristos 56531.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 56541.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 56551.1Skamil if (child == 0) { 56561.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 56571.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 56581.1Skamil 56591.99Skamil if (masked) { 56601.99Skamil sigemptyset(&intmask); 56611.99Skamil sigaddset(&intmask, SIGTRAP); 56621.99Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 56631.99Skamil } 56641.99Skamil 56651.99Skamil if (ignored) { 56661.99Skamil memset(&sa, 0, sizeof(sa)); 56671.99Skamil sa.sa_handler = SIG_IGN; 56681.99Skamil sigemptyset(&sa.sa_mask); 56691.99Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 56701.99Skamil } 56711.1Skamil 56721.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 56731.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 56741.1Skamil 56751.99Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 56761.1Skamil 56771.1Skamil if (child2 == 0) 56781.1Skamil _exit(exitval2); 56791.1Skamil 56801.1Skamil FORKEE_REQUIRE_SUCCESS 56811.99Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 56821.1Skamil 56831.1Skamil forkee_status_exited(status, exitval2); 56841.1Skamil 56851.13Schristos DPRINTF("Before exiting of the child process\n"); 56861.1Skamil _exit(exitval); 56871.1Skamil } 56881.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 56891.1Skamil 56901.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56911.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56921.1Skamil 56931.1Skamil validate_status_stopped(status, sigval); 56941.1Skamil 56951.99Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 56961.99Skamil SYSCALL_REQUIRE( 56971.99Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 56981.99Skamil 56991.99Skamil DPRINTF("Before checking siginfo_t\n"); 57001.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 57011.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 57021.1Skamil 57031.99Skamil name[0] = CTL_KERN, 57041.99Skamil name[1] = KERN_PROC2, 57051.99Skamil name[2] = KERN_PROC_PID; 57061.99Skamil name[3] = child; 57071.99Skamil name[4] = sizeof(kp); 57081.99Skamil name[5] = 1; 57091.1Skamil 57101.99Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 57111.1Skamil 57121.99Skamil if (masked) 57131.99Skamil kp_sigmask = kp.p_sigmask; 57141.1Skamil 57151.99Skamil if (ignored) 57161.99Skamil kp_sigignore = kp.p_sigignore; 57171.1Skamil 57181.99Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 57191.99Skamil trackfork ? "|PTRACE_FORK" : "", 57201.99Skamil trackvfork ? "|PTRACE_VFORK" : "", 57211.99Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 57221.99Skamil event.pe_set_event = 0; 57231.99Skamil if (trackfork) 57241.99Skamil event.pe_set_event |= PTRACE_FORK; 57251.99Skamil if (trackvfork) 57261.99Skamil event.pe_set_event |= PTRACE_VFORK; 57271.99Skamil if (trackvforkdone) 57281.99Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 57291.99Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 57301.1Skamil 57311.99Skamil DPRINTF("Before resuming the child process where it left off and " 57321.99Skamil "without signal to be sent\n"); 57331.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 57341.1Skamil 57351.99Skamil if (trackfork || trackvfork) { 57361.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 57371.99Skamil child); 57381.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 57391.99Skamil child); 57401.1Skamil 57411.99Skamil validate_status_stopped(status, SIGTRAP); 57421.1Skamil 57431.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 57441.1Skamil 57451.99Skamil if (masked) { 57461.99Skamil DPRINTF("kp_sigmask=" 57471.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 57481.99Skamil PRIx32 "\n", 57491.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 57501.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 57511.1Skamil 57521.99Skamil DPRINTF("kp.p_sigmask=" 57531.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 57541.99Skamil PRIx32 "\n", 57551.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 57561.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 57571.1Skamil 57581.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 57591.99Skamil sizeof(kp_sigmask))); 57601.99Skamil } 57611.1Skamil 57621.99Skamil if (ignored) { 57631.99Skamil DPRINTF("kp_sigignore=" 57641.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 57651.99Skamil PRIx32 "\n", 57661.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 57671.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 57681.1Skamil 57691.99Skamil DPRINTF("kp.p_sigignore=" 57701.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 57711.99Skamil PRIx32 "\n", 57721.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 57731.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 57741.1Skamil 57751.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 57761.99Skamil sizeof(kp_sigignore))); 57771.99Skamil } 57781.1Skamil 57791.99Skamil SYSCALL_REQUIRE( 57801.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 57811.99Skamil if (trackfork) { 57821.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 57831.99Skamil PTRACE_FORK); 57841.99Skamil } 57851.99Skamil if (trackvfork) { 57861.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 57871.99Skamil PTRACE_VFORK); 57881.99Skamil } 57891.1Skamil 57901.99Skamil child2 = state.pe_other_pid; 57911.99Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 57921.1Skamil 57931.99Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 57941.99Skamil "%d\n", TWAIT_FNAME, child2, child); 57951.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 57961.99Skamil child2); 57971.1Skamil 57981.99Skamil validate_status_stopped(status, SIGTRAP); 57991.1Skamil 58001.99Skamil name[3] = child2; 58011.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 58021.1Skamil 58031.99Skamil if (masked) { 58041.99Skamil DPRINTF("kp_sigmask=" 58051.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58061.99Skamil PRIx32 "\n", 58071.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 58081.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 58091.1Skamil 58101.99Skamil DPRINTF("kp.p_sigmask=" 58111.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58121.99Skamil PRIx32 "\n", 58131.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 58141.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 58151.14Schristos 58161.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 58171.99Skamil sizeof(kp_sigmask))); 58181.99Skamil } 58191.1Skamil 58201.99Skamil if (ignored) { 58211.99Skamil DPRINTF("kp_sigignore=" 58221.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58231.99Skamil PRIx32 "\n", 58241.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 58251.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 58261.1Skamil 58271.99Skamil DPRINTF("kp.p_sigignore=" 58281.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58291.99Skamil PRIx32 "\n", 58301.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 58311.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 58321.1Skamil 58331.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 58341.99Skamil sizeof(kp_sigignore))); 58351.99Skamil } 58361.1Skamil 58371.99Skamil SYSCALL_REQUIRE( 58381.99Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 58391.99Skamil if (trackfork) { 58401.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 58411.99Skamil PTRACE_FORK); 58421.99Skamil } 58431.99Skamil if (trackvfork) { 58441.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 58451.99Skamil PTRACE_VFORK); 58461.99Skamil } 58471.1Skamil 58481.99Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 58491.1Skamil 58501.99Skamil DPRINTF("Before resuming the forkee process where it left off " 58511.99Skamil "and without signal to be sent\n"); 58521.99Skamil SYSCALL_REQUIRE( 58531.99Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 58541.1Skamil 58551.99Skamil DPRINTF("Before resuming the child process where it left off " 58561.99Skamil "and without signal to be sent\n"); 58571.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 58581.1Skamil } 58591.1Skamil 58601.99Skamil if (trackvforkdone) { 58611.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 58621.99Skamil child); 58631.99Skamil TWAIT_REQUIRE_SUCCESS( 58641.99Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 58651.1Skamil 58661.99Skamil validate_status_stopped(status, SIGTRAP); 58671.1Skamil 58681.99Skamil name[3] = child; 58691.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 58701.1Skamil 58711.102Skamil /* 58721.102Skamil * SIGCHLD is now pending in the signal queue and 58731.102Skamil * the kernel presents it to userland as a masked signal. 58741.102Skamil */ 58751.102Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 58761.102Skamil 58771.99Skamil if (masked) { 58781.99Skamil DPRINTF("kp_sigmask=" 58791.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58801.99Skamil PRIx32 "\n", 58811.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 58821.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 58831.1Skamil 58841.99Skamil DPRINTF("kp.p_sigmask=" 58851.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58861.99Skamil PRIx32 "\n", 58871.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 58881.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 58891.1Skamil 58901.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 58911.99Skamil sizeof(kp_sigmask))); 58921.99Skamil } 58931.1Skamil 58941.99Skamil if (ignored) { 58951.99Skamil DPRINTF("kp_sigignore=" 58961.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 58971.99Skamil PRIx32 "\n", 58981.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 58991.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 59001.1Skamil 59011.99Skamil DPRINTF("kp.p_sigignore=" 59021.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 59031.99Skamil PRIx32 "\n", 59041.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 59051.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 59061.1Skamil 59071.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 59081.99Skamil sizeof(kp_sigignore))); 59091.99Skamil } 59101.1Skamil 59111.99Skamil SYSCALL_REQUIRE( 59121.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 59131.99Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 59141.1Skamil 59151.99Skamil child2 = state.pe_other_pid; 59161.99Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 59171.99Skamil child2); 59181.1Skamil 59191.99Skamil DPRINTF("Before resuming the child process where it left off " 59201.99Skamil "and without signal to be sent\n"); 59211.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 59221.99Skamil } 59231.1Skamil 59241.99Skamil if (trackfork || trackvfork) { 59251.99Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 59261.99Skamil "\n", TWAIT_FNAME); 59271.99Skamil TWAIT_REQUIRE_SUCCESS( 59281.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 59291.1Skamil 59301.99Skamil validate_status_exited(status, exitval2); 59311.1Skamil 59321.99Skamil DPRINTF("Before calling %s() for the forkee - expected no " 59331.99Skamil "process\n", TWAIT_FNAME); 59341.99Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 59351.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 59361.99Skamil } 59371.1Skamil 59381.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 59391.1Skamil "SIGCHLD\n", TWAIT_FNAME); 59401.57Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 59411.1Skamil 59421.1Skamil validate_status_stopped(status, SIGCHLD); 59431.1Skamil 59441.57Skamil DPRINTF("Before resuming the child process where it left off and " 59451.1Skamil "without signal to be sent\n"); 59461.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 59471.1Skamil 59481.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 59491.1Skamil TWAIT_FNAME); 59501.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 59511.1Skamil 59521.1Skamil validate_status_exited(status, exitval); 59531.1Skamil 59541.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 59551.57Skamil TWAIT_FNAME); 59561.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 59571.1Skamil} 59581.1Skamil 59591.99Skamil#define FORK2_TEST(name,trackfork,trackvfork,trackvforkdone, \ 59601.99Skamil masked,ignored) \ 59611.99SkamilATF_TC(name); \ 59621.99SkamilATF_TC_HEAD(name, tc) \ 59631.99Skamil{ \ 59641.99Skamil atf_tc_set_md_var(tc, "descr", "Verify that %s%s%s is caught " \ 59651.99Skamil "regardless of signal %s%s", \ 59661.99Skamil trackfork ? "PTRACE_FORK" : "", \ 59671.99Skamil trackvfork ? "PTRACE_VFORK" : "", \ 59681.99Skamil trackvforkdone ? "PTRACE_VFORK_DONE" : "", \ 59691.99Skamil masked ? "masked" : "", ignored ? "ignored" : ""); \ 59701.99Skamil} \ 59711.99Skamil \ 59721.99SkamilATF_TC_BODY(name, tc) \ 59731.99Skamil{ \ 59741.99Skamil \ 59751.99Skamil fork2_body(trackfork, trackvfork, trackvforkdone, masked, \ 59761.99Skamil ignored); \ 59771.1Skamil} 59781.1Skamil 59791.99SkamilFORK2_TEST(fork_singalmasked, true, false, false, true, false) 59801.99SkamilFORK2_TEST(fork_singalignored, true, false, false, false, true) 59811.110Skamil#if TEST_VFORK_ENABLED 59821.99SkamilFORK2_TEST(vfork_singalmasked, false, true, false, true, false) 59831.99SkamilFORK2_TEST(vfork_singalignored, false, true, false, false, true) 59841.99SkamilFORK2_TEST(vforkdone_singalmasked, false, false, true, true, false) 59851.99SkamilFORK2_TEST(vforkdone_singalignored, false, false, true, false, true) 59861.1Skamil#endif 59871.110Skamil#endif 59881.1Skamil 59891.99Skamil/// ---------------------------------------------------------------------------- 59901.1Skamil 59911.83Skamilvolatile lwpid_t the_lwp_id = 0; 59921.83Skamil 59931.83Skamilstatic void 59941.83Skamillwp_main_func(void *arg) 59951.83Skamil{ 59961.83Skamil the_lwp_id = _lwp_self(); 59971.83Skamil _lwp_exit(); 59981.83Skamil} 59991.83Skamil 60001.1SkamilATF_TC(signal9); 60011.1SkamilATF_TC_HEAD(signal9, tc) 60021.1Skamil{ 60031.1Skamil atf_tc_set_md_var(tc, "descr", 60041.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 60051.1Skamil "catching PTRACE_LWP_CREATE breakpoint"); 60061.1Skamil} 60071.1Skamil 60081.1SkamilATF_TC_BODY(signal9, tc) 60091.1Skamil{ 60101.1Skamil const int exitval = 5; 60111.1Skamil const int sigval = SIGSTOP; 60121.1Skamil const int sigmasked = SIGTRAP; 60131.1Skamil pid_t child, wpid; 60141.1Skamil#if defined(TWAIT_HAVE_STATUS) 60151.1Skamil int status; 60161.1Skamil#endif 60171.1Skamil sigset_t intmask; 60181.1Skamil ptrace_state_t state; 60191.1Skamil const int slen = sizeof(state); 60201.1Skamil ptrace_event_t event; 60211.1Skamil const int elen = sizeof(event); 60221.1Skamil ucontext_t uc; 60231.1Skamil lwpid_t lid; 60241.1Skamil static const size_t ssize = 16*1024; 60251.1Skamil void *stack; 60261.1Skamil 60271.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 60281.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 60291.1Skamil if (child == 0) { 60301.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 60311.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 60321.1Skamil 60331.1Skamil sigemptyset(&intmask); 60341.1Skamil sigaddset(&intmask, sigmasked); 60351.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 60361.1Skamil 60371.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 60381.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 60391.1Skamil 60401.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 60411.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 60421.1Skamil 60431.13Schristos DPRINTF("Before making context for new lwp in child\n"); 60441.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 60451.1Skamil 60461.13Schristos DPRINTF("Before creating new in child\n"); 60471.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 60481.1Skamil 60491.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 60501.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 60511.1Skamil 60521.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 60531.1Skamil "are the same\n", lid, the_lwp_id); 60541.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 60551.1Skamil 60561.13Schristos DPRINTF("Before exiting of the child process\n"); 60571.1Skamil _exit(exitval); 60581.1Skamil } 60591.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 60601.1Skamil 60611.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 60621.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60631.1Skamil 60641.1Skamil validate_status_stopped(status, sigval); 60651.1Skamil 60661.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 60671.1Skamil event.pe_set_event = PTRACE_LWP_CREATE; 60681.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 60691.1Skamil 60701.13Schristos DPRINTF("Before resuming the child process where it left off and " 60711.1Skamil "without signal to be sent\n"); 60721.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60731.1Skamil 60741.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 60751.1Skamil "SIGTRAP\n", TWAIT_FNAME); 60761.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60771.1Skamil 60781.1Skamil validate_status_stopped(status, sigmasked); 60791.1Skamil 60801.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 60811.1Skamil 60821.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE); 60831.1Skamil 60841.1Skamil lid = state.pe_lwp; 60851.13Schristos DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 60861.1Skamil 60871.13Schristos DPRINTF("Before resuming the child process where it left off and " 60881.1Skamil "without signal to be sent\n"); 60891.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60901.1Skamil 60911.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 60921.1Skamil TWAIT_FNAME); 60931.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60941.1Skamil 60951.1Skamil validate_status_exited(status, exitval); 60961.1Skamil 60971.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 60981.1Skamil TWAIT_FNAME); 60991.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 61001.1Skamil} 61011.1Skamil 61021.1SkamilATF_TC(signal10); 61031.1SkamilATF_TC_HEAD(signal10, tc) 61041.1Skamil{ 61051.1Skamil atf_tc_set_md_var(tc, "descr", 61061.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 61071.1Skamil "catching PTRACE_LWP_EXIT breakpoint"); 61081.1Skamil} 61091.1Skamil 61101.1SkamilATF_TC_BODY(signal10, tc) 61111.1Skamil{ 61121.1Skamil const int exitval = 5; 61131.1Skamil const int sigval = SIGSTOP; 61141.1Skamil const int sigmasked = SIGTRAP; 61151.1Skamil pid_t child, wpid; 61161.1Skamil#if defined(TWAIT_HAVE_STATUS) 61171.1Skamil int status; 61181.1Skamil#endif 61191.1Skamil sigset_t intmask; 61201.1Skamil ptrace_state_t state; 61211.1Skamil const int slen = sizeof(state); 61221.1Skamil ptrace_event_t event; 61231.1Skamil const int elen = sizeof(event); 61241.1Skamil ucontext_t uc; 61251.1Skamil lwpid_t lid; 61261.1Skamil static const size_t ssize = 16*1024; 61271.1Skamil void *stack; 61281.1Skamil 61291.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 61301.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 61311.1Skamil if (child == 0) { 61321.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 61331.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 61341.1Skamil 61351.1Skamil sigemptyset(&intmask); 61361.1Skamil sigaddset(&intmask, sigmasked); 61371.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 61381.1Skamil 61391.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 61401.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 61411.1Skamil 61421.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 61431.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 61441.1Skamil 61451.13Schristos DPRINTF("Before making context for new lwp in child\n"); 61461.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 61471.1Skamil 61481.13Schristos DPRINTF("Before creating new in child\n"); 61491.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 61501.1Skamil 61511.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 61521.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 61531.1Skamil 61541.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 61551.1Skamil "are the same\n", lid, the_lwp_id); 61561.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 61571.1Skamil 61581.13Schristos DPRINTF("Before exiting of the child process\n"); 61591.1Skamil _exit(exitval); 61601.1Skamil } 61611.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 61621.1Skamil 61631.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 61641.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61651.1Skamil 61661.1Skamil validate_status_stopped(status, sigval); 61671.1Skamil 61681.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 61691.1Skamil event.pe_set_event = PTRACE_LWP_EXIT; 61701.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 61711.1Skamil 61721.13Schristos DPRINTF("Before resuming the child process where it left off and " 61731.1Skamil "without signal to be sent\n"); 61741.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 61751.1Skamil 61761.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 61771.1Skamil "SIGTRAP\n", TWAIT_FNAME); 61781.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61791.1Skamil 61801.1Skamil validate_status_stopped(status, sigmasked); 61811.1Skamil 61821.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 61831.1Skamil 61841.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT); 61851.1Skamil 61861.1Skamil lid = state.pe_lwp; 61871.13Schristos DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 61881.1Skamil 61891.13Schristos DPRINTF("Before resuming the child process where it left off and " 61901.1Skamil "without signal to be sent\n"); 61911.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 61921.1Skamil 61931.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 61941.1Skamil TWAIT_FNAME); 61951.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61961.1Skamil 61971.1Skamil validate_status_exited(status, exitval); 61981.1Skamil 61991.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 62001.1Skamil TWAIT_FNAME); 62011.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 62021.1Skamil} 62031.1Skamil 62041.1Skamilstatic void 62051.1Skamillwp_main_stop(void *arg) 62061.1Skamil{ 62071.1Skamil the_lwp_id = _lwp_self(); 62081.1Skamil 62091.1Skamil raise(SIGTRAP); 62101.1Skamil 62111.1Skamil _lwp_exit(); 62121.1Skamil} 62131.1Skamil 62141.1SkamilATF_TC(suspend1); 62151.1SkamilATF_TC_HEAD(suspend1, tc) 62161.1Skamil{ 62171.1Skamil atf_tc_set_md_var(tc, "descr", 62181.1Skamil "Verify that a thread can be suspended by a debugger and later " 62191.1Skamil "resumed by a tracee"); 62201.1Skamil} 62211.1Skamil 62221.1SkamilATF_TC_BODY(suspend1, tc) 62231.1Skamil{ 62241.1Skamil const int exitval = 5; 62251.1Skamil const int sigval = SIGSTOP; 62261.1Skamil pid_t child, wpid; 62271.1Skamil#if defined(TWAIT_HAVE_STATUS) 62281.1Skamil int status; 62291.1Skamil#endif 62301.1Skamil ucontext_t uc; 62311.1Skamil lwpid_t lid; 62321.1Skamil static const size_t ssize = 16*1024; 62331.1Skamil void *stack; 62341.1Skamil struct ptrace_lwpinfo pl; 62351.1Skamil struct ptrace_siginfo psi; 62361.1Skamil volatile int go = 0; 62371.1Skamil 62381.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 62391.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 62401.1Skamil if (child == 0) { 62411.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 62421.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 62431.1Skamil 62441.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 62451.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 62461.1Skamil 62471.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 62481.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 62491.1Skamil 62501.13Schristos DPRINTF("Before making context for new lwp in child\n"); 62511.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 62521.1Skamil 62531.13Schristos DPRINTF("Before creating new in child\n"); 62541.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 62551.1Skamil 62561.1Skamil while (go == 0) 62571.1Skamil continue; 62581.1Skamil 62591.1Skamil raise(SIGINT); 62601.1Skamil 62611.1Skamil FORKEE_ASSERT(_lwp_continue(lid) == 0); 62621.1Skamil 62631.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 62641.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 62651.1Skamil 62661.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 62671.1Skamil "are the same\n", lid, the_lwp_id); 62681.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 62691.1Skamil 62701.13Schristos DPRINTF("Before exiting of the child process\n"); 62711.1Skamil _exit(exitval); 62721.1Skamil } 62731.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 62741.1Skamil 62751.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 62761.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62771.1Skamil 62781.1Skamil validate_status_stopped(status, sigval); 62791.1Skamil 62801.13Schristos DPRINTF("Before resuming the child process where it left off and " 62811.1Skamil "without signal to be sent\n"); 62821.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 62831.1Skamil 62841.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 62851.1Skamil "SIGTRAP\n", TWAIT_FNAME); 62861.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62871.1Skamil 62881.1Skamil validate_status_stopped(status, SIGTRAP); 62891.1Skamil 62901.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 62911.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 62921.1Skamil 62931.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 62941.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 62951.1Skamil 62961.13Schristos DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n", 62971.1Skamil child, getpid()); 62981.13Schristos SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1); 62991.1Skamil 63001.13Schristos DPRINTF("Before resuming the child process where it left off and " 63011.1Skamil "without signal to be sent\n"); 63021.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63031.1Skamil 63041.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 63051.1Skamil "SIGINT\n", TWAIT_FNAME); 63061.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63071.1Skamil 63081.1Skamil validate_status_stopped(status, SIGINT); 63091.1Skamil 63101.1Skamil pl.pl_lwpid = 0; 63111.1Skamil 63121.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 63131.1Skamil while (pl.pl_lwpid != 0) { 63141.1Skamil 63151.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 63161.1Skamil switch (pl.pl_lwpid) { 63171.1Skamil case 1: 63181.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 63191.1Skamil break; 63201.1Skamil case 2: 63211.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 63221.1Skamil break; 63231.1Skamil } 63241.1Skamil } 63251.1Skamil 63261.13Schristos DPRINTF("Before resuming the child process where it left off and " 63271.1Skamil "without signal to be sent\n"); 63281.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63291.1Skamil 63301.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 63311.1Skamil TWAIT_FNAME); 63321.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63331.1Skamil 63341.1Skamil validate_status_exited(status, exitval); 63351.1Skamil 63361.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 63371.1Skamil TWAIT_FNAME); 63381.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 63391.1Skamil} 63401.1Skamil 63411.1SkamilATF_TC(suspend2); 63421.1SkamilATF_TC_HEAD(suspend2, tc) 63431.1Skamil{ 63441.1Skamil atf_tc_set_md_var(tc, "descr", 63451.1Skamil "Verify that the while the only thread within a process is " 63461.1Skamil "suspended, the whole process cannot be unstopped"); 63471.1Skamil} 63481.1Skamil 63491.1SkamilATF_TC_BODY(suspend2, tc) 63501.1Skamil{ 63511.1Skamil const int exitval = 5; 63521.1Skamil const int sigval = SIGSTOP; 63531.1Skamil pid_t child, wpid; 63541.1Skamil#if defined(TWAIT_HAVE_STATUS) 63551.1Skamil int status; 63561.1Skamil#endif 63571.1Skamil struct ptrace_siginfo psi; 63581.1Skamil 63591.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 63601.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 63611.1Skamil if (child == 0) { 63621.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 63631.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 63641.1Skamil 63651.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 63661.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 63671.1Skamil 63681.13Schristos DPRINTF("Before exiting of the child process\n"); 63691.1Skamil _exit(exitval); 63701.1Skamil } 63711.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 63721.1Skamil 63731.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 63741.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63751.1Skamil 63761.1Skamil validate_status_stopped(status, sigval); 63771.1Skamil 63781.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 63791.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 63801.1Skamil 63811.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 63821.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 63831.1Skamil 63841.13Schristos DPRINTF("Before resuming the child process where it left off and " 63851.1Skamil "without signal to be sent\n"); 63861.1Skamil ATF_REQUIRE_ERRNO(EDEADLK, 63871.1Skamil ptrace(PT_CONTINUE, child, (void *)1, 0) == -1); 63881.1Skamil 63891.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 63901.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 63911.1Skamil 63921.13Schristos DPRINTF("Before resuming the child process where it left off and " 63931.1Skamil "without signal to be sent\n"); 63941.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63951.1Skamil 63961.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 63971.1Skamil TWAIT_FNAME); 63981.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63991.1Skamil 64001.1Skamil validate_status_exited(status, exitval); 64011.1Skamil 64021.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 64031.1Skamil TWAIT_FNAME); 64041.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 64051.1Skamil} 64061.1Skamil 64071.1SkamilATF_TC(resume1); 64081.1SkamilATF_TC_HEAD(resume1, tc) 64091.1Skamil{ 64101.1Skamil atf_tc_set_md_var(tc, "descr", 64111.1Skamil "Verify that a thread can be suspended by a debugger and later " 64121.1Skamil "resumed by the debugger"); 64131.1Skamil} 64141.1Skamil 64151.1SkamilATF_TC_BODY(resume1, tc) 64161.1Skamil{ 64171.1Skamil struct msg_fds fds; 64181.1Skamil const int exitval = 5; 64191.1Skamil const int sigval = SIGSTOP; 64201.1Skamil pid_t child, wpid; 64211.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 64221.1Skamil#if defined(TWAIT_HAVE_STATUS) 64231.1Skamil int status; 64241.1Skamil#endif 64251.1Skamil ucontext_t uc; 64261.1Skamil lwpid_t lid; 64271.1Skamil static const size_t ssize = 16*1024; 64281.1Skamil void *stack; 64291.1Skamil struct ptrace_lwpinfo pl; 64301.1Skamil struct ptrace_siginfo psi; 64311.1Skamil 64321.13Schristos SYSCALL_REQUIRE(msg_open(&fds) == 0); 64331.1Skamil 64341.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 64351.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 64361.1Skamil if (child == 0) { 64371.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 64381.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 64391.1Skamil 64401.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 64411.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 64421.1Skamil 64431.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 64441.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 64451.1Skamil 64461.13Schristos DPRINTF("Before making context for new lwp in child\n"); 64471.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 64481.1Skamil 64491.13Schristos DPRINTF("Before creating new in child\n"); 64501.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 64511.1Skamil 64521.1Skamil CHILD_TO_PARENT("Message", fds, msg); 64531.1Skamil 64541.1Skamil raise(SIGINT); 64551.1Skamil 64561.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 64571.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 64581.1Skamil 64591.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 64601.1Skamil "are the same\n", lid, the_lwp_id); 64611.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 64621.1Skamil 64631.13Schristos DPRINTF("Before exiting of the child process\n"); 64641.1Skamil _exit(exitval); 64651.1Skamil } 64661.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 64671.1Skamil 64681.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 64691.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64701.1Skamil 64711.1Skamil validate_status_stopped(status, sigval); 64721.1Skamil 64731.13Schristos DPRINTF("Before resuming the child process where it left off and " 64741.1Skamil "without signal to be sent\n"); 64751.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64761.1Skamil 64771.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 64781.1Skamil "SIGTRAP\n", TWAIT_FNAME); 64791.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64801.1Skamil 64811.1Skamil validate_status_stopped(status, SIGTRAP); 64821.1Skamil 64831.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 64841.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 64851.1Skamil 64861.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 64871.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 64881.1Skamil 64891.1Skamil PARENT_FROM_CHILD("Message", fds, msg); 64901.1Skamil 64911.13Schristos DPRINTF("Before resuming the child process where it left off and " 64921.1Skamil "without signal to be sent\n"); 64931.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64941.1Skamil 64951.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 64961.1Skamil "SIGINT\n", TWAIT_FNAME); 64971.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64981.1Skamil 64991.1Skamil validate_status_stopped(status, SIGINT); 65001.1Skamil 65011.1Skamil pl.pl_lwpid = 0; 65021.1Skamil 65031.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 65041.1Skamil while (pl.pl_lwpid != 0) { 65051.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 65061.1Skamil switch (pl.pl_lwpid) { 65071.1Skamil case 1: 65081.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 65091.1Skamil break; 65101.1Skamil case 2: 65111.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 65121.1Skamil break; 65131.1Skamil } 65141.1Skamil } 65151.1Skamil 65161.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 65171.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 65181.1Skamil 65191.13Schristos DPRINTF("Before resuming the child process where it left off and " 65201.1Skamil "without signal to be sent\n"); 65211.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65221.1Skamil 65231.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 65241.1Skamil TWAIT_FNAME); 65251.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65261.1Skamil 65271.1Skamil validate_status_exited(status, exitval); 65281.1Skamil 65291.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 65301.1Skamil TWAIT_FNAME); 65311.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 65321.1Skamil 65331.1Skamil msg_close(&fds); 65341.1Skamil} 65351.1Skamil 65361.1SkamilATF_TC(syscall1); 65371.1SkamilATF_TC_HEAD(syscall1, tc) 65381.1Skamil{ 65391.1Skamil atf_tc_set_md_var(tc, "descr", 65401.1Skamil "Verify that getpid(2) can be traced with PT_SYSCALL"); 65411.1Skamil} 65421.1Skamil 65431.1SkamilATF_TC_BODY(syscall1, tc) 65441.1Skamil{ 65451.1Skamil const int exitval = 5; 65461.1Skamil const int sigval = SIGSTOP; 65471.1Skamil pid_t child, wpid; 65481.1Skamil#if defined(TWAIT_HAVE_STATUS) 65491.1Skamil int status; 65501.1Skamil#endif 65511.1Skamil struct ptrace_siginfo info; 65521.1Skamil memset(&info, 0, sizeof(info)); 65531.1Skamil 65541.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 65551.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 65561.1Skamil if (child == 0) { 65571.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 65581.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 65591.1Skamil 65601.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 65611.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 65621.1Skamil 65631.1Skamil syscall(SYS_getpid); 65641.1Skamil 65651.13Schristos DPRINTF("Before exiting of the child process\n"); 65661.1Skamil _exit(exitval); 65671.1Skamil } 65681.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 65691.1Skamil 65701.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65711.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65721.1Skamil 65731.1Skamil validate_status_stopped(status, sigval); 65741.1Skamil 65751.13Schristos DPRINTF("Before resuming the child process where it left off and " 65761.1Skamil "without signal to be sent\n"); 65771.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 65781.1Skamil 65791.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65801.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65811.1Skamil 65821.1Skamil validate_status_stopped(status, SIGTRAP); 65831.1Skamil 65841.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 65851.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 65861.1Skamil 65871.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 65881.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 65891.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 65901.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE); 65911.1Skamil 65921.13Schristos DPRINTF("Before resuming the child process where it left off and " 65931.1Skamil "without signal to be sent\n"); 65941.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 65951.1Skamil 65961.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65971.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65981.1Skamil 65991.1Skamil validate_status_stopped(status, SIGTRAP); 66001.1Skamil 66011.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 66021.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 66031.1Skamil 66041.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 66051.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 66061.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 66071.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX); 66081.1Skamil 66091.13Schristos DPRINTF("Before resuming the child process where it left off and " 66101.1Skamil "without signal to be sent\n"); 66111.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66121.1Skamil 66131.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66141.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66151.1Skamil 66161.1Skamil validate_status_exited(status, exitval); 66171.1Skamil 66181.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66191.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 66201.1Skamil} 66211.1Skamil 66221.1SkamilATF_TC(syscallemu1); 66231.1SkamilATF_TC_HEAD(syscallemu1, tc) 66241.1Skamil{ 66251.1Skamil atf_tc_set_md_var(tc, "descr", 66261.1Skamil "Verify that exit(2) can be intercepted with PT_SYSCALLEMU"); 66271.1Skamil} 66281.1Skamil 66291.1SkamilATF_TC_BODY(syscallemu1, tc) 66301.1Skamil{ 66311.1Skamil const int exitval = 5; 66321.1Skamil const int sigval = SIGSTOP; 66331.1Skamil pid_t child, wpid; 66341.1Skamil#if defined(TWAIT_HAVE_STATUS) 66351.1Skamil int status; 66361.1Skamil#endif 66371.1Skamil 66381.6Skamil#if defined(__sparc__) && !defined(__sparc64__) 66391.6Skamil /* syscallemu does not work on sparc (32-bit) */ 66401.6Skamil atf_tc_expect_fail("PR kern/52166"); 66411.6Skamil#endif 66421.6Skamil 66431.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 66441.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 66451.1Skamil if (child == 0) { 66461.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 66471.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 66481.1Skamil 66491.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 66501.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 66511.1Skamil 66521.1Skamil syscall(SYS_exit, 100); 66531.1Skamil 66541.13Schristos DPRINTF("Before exiting of the child process\n"); 66551.1Skamil _exit(exitval); 66561.1Skamil } 66571.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 66581.1Skamil 66591.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66601.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66611.1Skamil 66621.1Skamil validate_status_stopped(status, sigval); 66631.1Skamil 66641.13Schristos DPRINTF("Before resuming the child process where it left off and " 66651.1Skamil "without signal to be sent\n"); 66661.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 66671.1Skamil 66681.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66691.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66701.1Skamil 66711.1Skamil validate_status_stopped(status, SIGTRAP); 66721.1Skamil 66731.13Schristos DPRINTF("Set SYSCALLEMU for intercepted syscall\n"); 66741.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1); 66751.1Skamil 66761.13Schristos DPRINTF("Before resuming the child process where it left off and " 66771.1Skamil "without signal to be sent\n"); 66781.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 66791.1Skamil 66801.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66811.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66821.1Skamil 66831.1Skamil validate_status_stopped(status, SIGTRAP); 66841.1Skamil 66851.13Schristos DPRINTF("Before resuming the child process where it left off and " 66861.1Skamil "without signal to be sent\n"); 66871.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66881.1Skamil 66891.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66901.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 66911.1Skamil 66921.1Skamil validate_status_exited(status, exitval); 66931.1Skamil 66941.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 66951.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 66961.1Skamil} 66971.1Skamil 66981.103Skamil/// ---------------------------------------------------------------------------- 66991.103Skamil 67001.106Skamilstatic void 67011.106Skamilclone_body(int flags, bool trackfork, bool trackvfork, 67021.106Skamil bool trackvforkdone) 67031.106Skamil{ 67041.106Skamil const int exitval = 5; 67051.106Skamil const int exitval2 = 15; 67061.106Skamil const int sigval = SIGSTOP; 67071.106Skamil pid_t child, child2 = 0, wpid; 67081.106Skamil#if defined(TWAIT_HAVE_STATUS) 67091.106Skamil int status; 67101.106Skamil#endif 67111.106Skamil ptrace_state_t state; 67121.106Skamil const int slen = sizeof(state); 67131.106Skamil ptrace_event_t event; 67141.106Skamil const int elen = sizeof(event); 67151.106Skamil 67161.106Skamil const size_t stack_size = 1024 * 1024; 67171.106Skamil void *stack, *stack_base; 67181.106Skamil 67191.106Skamil stack = malloc(stack_size); 67201.106Skamil ATF_REQUIRE(stack != NULL); 67211.106Skamil 67221.106Skamil#ifdef __MACHINE_STACK_GROWS_UP 67231.106Skamil stack_base = stack; 67241.106Skamil#else 67251.106Skamil stack_base = (char *)stack + stack_size; 67261.106Skamil#endif 67271.106Skamil 67281.106Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 67291.106Skamil SYSCALL_REQUIRE((child = fork()) != -1); 67301.106Skamil if (child == 0) { 67311.106Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 67321.106Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 67331.106Skamil 67341.106Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 67351.106Skamil FORKEE_ASSERT(raise(sigval) == 0); 67361.106Skamil 67371.106Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 67381.106Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 67391.106Skamil 67401.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 67411.106Skamil child2); 67421.106Skamil 67431.106Skamil // XXX WALLSIG? 67441.106Skamil FORKEE_REQUIRE_SUCCESS 67451.106Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 67461.106Skamil 67471.106Skamil forkee_status_exited(status, exitval2); 67481.106Skamil 67491.106Skamil DPRINTF("Before exiting of the child process\n"); 67501.106Skamil _exit(exitval); 67511.106Skamil } 67521.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 67531.106Skamil 67541.106Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 67551.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67561.106Skamil 67571.106Skamil validate_status_stopped(status, sigval); 67581.106Skamil 67591.106Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 67601.106Skamil trackfork ? "|PTRACE_FORK" : "", 67611.106Skamil trackvfork ? "|PTRACE_VFORK" : "", 67621.106Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 67631.106Skamil event.pe_set_event = 0; 67641.106Skamil if (trackfork) 67651.106Skamil event.pe_set_event |= PTRACE_FORK; 67661.106Skamil if (trackvfork) 67671.106Skamil event.pe_set_event |= PTRACE_VFORK; 67681.106Skamil if (trackvforkdone) 67691.106Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 67701.106Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 67711.106Skamil 67721.106Skamil DPRINTF("Before resuming the child process where it left off and " 67731.106Skamil "without signal to be sent\n"); 67741.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 67751.106Skamil 67761.106Skamil#if defined(TWAIT_HAVE_PID) 67771.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 67781.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 67791.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 67801.106Skamil child); 67811.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 67821.106Skamil child); 67831.106Skamil 67841.106Skamil validate_status_stopped(status, SIGTRAP); 67851.106Skamil 67861.106Skamil SYSCALL_REQUIRE( 67871.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 67881.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 67891.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 67901.106Skamil PTRACE_FORK); 67911.106Skamil } 67921.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 67931.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 67941.106Skamil PTRACE_VFORK); 67951.106Skamil } 67961.106Skamil 67971.106Skamil child2 = state.pe_other_pid; 67981.106Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 67991.106Skamil 68001.106Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 68011.106Skamil "%d\n", TWAIT_FNAME, child2, child); 68021.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 68031.106Skamil child2); 68041.106Skamil 68051.106Skamil validate_status_stopped(status, SIGTRAP); 68061.106Skamil 68071.106Skamil SYSCALL_REQUIRE( 68081.106Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 68091.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 68101.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 68111.106Skamil PTRACE_FORK); 68121.106Skamil } 68131.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 68141.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 68151.106Skamil PTRACE_VFORK); 68161.106Skamil } 68171.106Skamil 68181.106Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 68191.106Skamil 68201.106Skamil DPRINTF("Before resuming the forkee process where it left off " 68211.106Skamil "and without signal to be sent\n"); 68221.106Skamil SYSCALL_REQUIRE( 68231.106Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 68241.106Skamil 68251.106Skamil DPRINTF("Before resuming the child process where it left off " 68261.106Skamil "and without signal to be sent\n"); 68271.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68281.106Skamil } 68291.106Skamil#endif 68301.106Skamil 68311.106Skamil if (trackvforkdone && (flags & CLONE_VFORK)) { 68321.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 68331.106Skamil child); 68341.106Skamil TWAIT_REQUIRE_SUCCESS( 68351.106Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 68361.106Skamil 68371.106Skamil validate_status_stopped(status, SIGTRAP); 68381.106Skamil 68391.106Skamil SYSCALL_REQUIRE( 68401.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 68411.106Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 68421.106Skamil 68431.106Skamil child2 = state.pe_other_pid; 68441.106Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 68451.106Skamil child2); 68461.106Skamil 68471.106Skamil DPRINTF("Before resuming the child process where it left off " 68481.106Skamil "and without signal to be sent\n"); 68491.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68501.106Skamil } 68511.106Skamil 68521.103Skamil#if defined(TWAIT_HAVE_PID) 68531.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 68541.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 68551.106Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 68561.106Skamil "\n", TWAIT_FNAME); 68571.106Skamil TWAIT_REQUIRE_SUCCESS( 68581.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 68591.106Skamil 68601.106Skamil validate_status_exited(status, exitval2); 68611.106Skamil 68621.106Skamil DPRINTF("Before calling %s() for the forkee - expected no " 68631.106Skamil "process\n", TWAIT_FNAME); 68641.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 68651.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 68661.106Skamil } 68671.106Skamil#endif 68681.106Skamil 68691.106Skamil DPRINTF("Before calling %s() for the child - expected stopped " 68701.106Skamil "SIGCHLD\n", TWAIT_FNAME); 68711.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68721.106Skamil 68731.106Skamil validate_status_stopped(status, SIGCHLD); 68741.106Skamil 68751.106Skamil DPRINTF("Before resuming the child process where it left off and " 68761.106Skamil "without signal to be sent\n"); 68771.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 68781.106Skamil 68791.106Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 68801.106Skamil TWAIT_FNAME); 68811.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 68821.106Skamil 68831.106Skamil validate_status_exited(status, exitval); 68841.103Skamil 68851.106Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 68861.106Skamil TWAIT_FNAME); 68871.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 68881.106Skamil} 68891.103Skamil 68901.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone) \ 68911.106SkamilATF_TC(name); \ 68921.106SkamilATF_TC_HEAD(name, tc) \ 68931.106Skamil{ \ 68941.106Skamil atf_tc_set_md_var(tc, "descr", "Verify clone(%s) " \ 68951.106Skamil "called with 0%s%s%s in EVENT_MASK", \ 68961.106Skamil #flags, \ 68971.106Skamil tfork ? "|PTRACE_FORK" : "", \ 68981.106Skamil tvfork ? "|PTRACE_VFORK" : "", \ 68991.106Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 69001.106Skamil} \ 69011.106Skamil \ 69021.106SkamilATF_TC_BODY(name, tc) \ 69031.106Skamil{ \ 69041.106Skamil \ 69051.106Skamil clone_body(flags, tfork, tvfork, tvforkdone); \ 69061.103Skamil} 69071.103Skamil 69081.106SkamilCLONE_TEST(clone1, 0, false, false, false) 69091.106Skamil#if defined(TWAIT_HAVE_PID) 69101.106SkamilCLONE_TEST(clone2, 0, true, false, false) 69111.106SkamilCLONE_TEST(clone3, 0, false, true, false) 69121.106SkamilCLONE_TEST(clone4, 0, true, true, false) 69131.106Skamil#endif 69141.106SkamilCLONE_TEST(clone5, 0, false, false, true) 69151.106Skamil#if defined(TWAIT_HAVE_PID) 69161.106SkamilCLONE_TEST(clone6, 0, true, false, true) 69171.106SkamilCLONE_TEST(clone7, 0, false, true, true) 69181.106SkamilCLONE_TEST(clone8, 0, true, true, true) 69191.106Skamil#endif 69201.106Skamil 69211.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false) 69221.106Skamil#if defined(TWAIT_HAVE_PID) 69231.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false) 69241.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false) 69251.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false) 69261.106Skamil#endif 69271.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true) 69281.106Skamil#if defined(TWAIT_HAVE_PID) 69291.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true) 69301.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true) 69311.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true) 69321.106Skamil#endif 69331.106Skamil 69341.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false) 69351.106Skamil#if defined(TWAIT_HAVE_PID) 69361.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false) 69371.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false) 69381.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false) 69391.106Skamil#endif 69401.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true) 69411.106Skamil#if defined(TWAIT_HAVE_PID) 69421.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true) 69431.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true) 69441.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true) 69451.106Skamil#endif 69461.106Skamil 69471.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false) 69481.106Skamil#if defined(TWAIT_HAVE_PID) 69491.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false) 69501.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false) 69511.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false) 69521.106Skamil#endif 69531.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true) 69541.106Skamil#if defined(TWAIT_HAVE_PID) 69551.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true) 69561.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true) 69571.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true) 69581.106Skamil#endif 69591.106Skamil 69601.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false) 69611.106Skamil#if defined(TWAIT_HAVE_PID) 69621.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false) 69631.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false) 69641.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false) 69651.106Skamil#endif 69661.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true) 69671.106Skamil#if defined(TWAIT_HAVE_PID) 69681.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true) 69691.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true) 69701.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true) 69711.106Skamil#endif 69721.106Skamil 69731.110Skamil#if TEST_VFORK_ENABLED 69741.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false) 69751.106Skamil#if defined(TWAIT_HAVE_PID) 69761.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false) 69771.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false) 69781.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false) 69791.106Skamil#endif 69801.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true) 69811.106Skamil#if defined(TWAIT_HAVE_PID) 69821.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true) 69831.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true) 69841.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true) 69851.106Skamil#endif 69861.110Skamil#endif 69871.106Skamil 69881.106Skamil/// ---------------------------------------------------------------------------- 69891.106Skamil 69901.106Skamil#if defined(TWAIT_HAVE_PID) 69911.103Skamilstatic void 69921.106Skamilclone_body2(int flags, bool masked, bool ignored) 69931.103Skamil{ 69941.103Skamil const int exitval = 5; 69951.103Skamil const int exitval2 = 15; 69961.103Skamil const int sigval = SIGSTOP; 69971.103Skamil pid_t child, child2 = 0, wpid; 69981.103Skamil#if defined(TWAIT_HAVE_STATUS) 69991.103Skamil int status; 70001.103Skamil#endif 70011.103Skamil ptrace_state_t state; 70021.103Skamil const int slen = sizeof(state); 70031.103Skamil ptrace_event_t event; 70041.103Skamil const int elen = sizeof(event); 70051.103Skamil struct sigaction sa; 70061.103Skamil struct ptrace_siginfo info; 70071.103Skamil sigset_t intmask; 70081.103Skamil struct kinfo_proc2 kp; 70091.103Skamil size_t len = sizeof(kp); 70101.103Skamil 70111.103Skamil int name[6]; 70121.103Skamil const size_t namelen = __arraycount(name); 70131.103Skamil ki_sigset_t kp_sigmask; 70141.103Skamil ki_sigset_t kp_sigignore; 70151.103Skamil 70161.103Skamil const size_t stack_size = 1024 * 1024; 70171.103Skamil void *stack, *stack_base; 70181.103Skamil 70191.103Skamil stack = malloc(stack_size); 70201.103Skamil ATF_REQUIRE(stack != NULL); 70211.103Skamil 70221.103Skamil#ifdef __MACHINE_STACK_GROWS_UP 70231.103Skamil stack_base = stack; 70241.103Skamil#else 70251.103Skamil stack_base = (char *)stack + stack_size; 70261.103Skamil#endif 70271.103Skamil 70281.103Skamil SYSCALL_REQUIRE((child = fork()) != -1); 70291.103Skamil if (child == 0) { 70301.103Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 70311.103Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 70321.103Skamil 70331.103Skamil if (masked) { 70341.103Skamil sigemptyset(&intmask); 70351.103Skamil sigaddset(&intmask, SIGTRAP); 70361.103Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 70371.103Skamil } 70381.103Skamil 70391.103Skamil if (ignored) { 70401.103Skamil memset(&sa, 0, sizeof(sa)); 70411.103Skamil sa.sa_handler = SIG_IGN; 70421.103Skamil sigemptyset(&sa.sa_mask); 70431.103Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 70441.103Skamil } 70451.103Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 70461.103Skamil FORKEE_ASSERT(raise(sigval) == 0); 70471.103Skamil 70481.103Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 70491.103Skamil flags); 70501.103Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 70511.103Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 70521.103Skamil 70531.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 70541.103Skamil child2); 70551.103Skamil 70561.103Skamil // XXX WALLSIG? 70571.103Skamil FORKEE_REQUIRE_SUCCESS 70581.103Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 70591.103Skamil 70601.103Skamil forkee_status_exited(status, exitval2); 70611.103Skamil 70621.103Skamil DPRINTF("Before exiting of the child process\n"); 70631.103Skamil _exit(exitval); 70641.103Skamil } 70651.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 70661.103Skamil 70671.103Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 70681.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 70691.103Skamil 70701.103Skamil validate_status_stopped(status, sigval); 70711.103Skamil 70721.103Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 70731.103Skamil SYSCALL_REQUIRE( 70741.103Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 70751.103Skamil 70761.103Skamil DPRINTF("Before checking siginfo_t\n"); 70771.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 70781.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 70791.103Skamil 70801.103Skamil name[0] = CTL_KERN, 70811.103Skamil name[1] = KERN_PROC2, 70821.103Skamil name[2] = KERN_PROC_PID; 70831.103Skamil name[3] = child; 70841.103Skamil name[4] = sizeof(kp); 70851.103Skamil name[5] = 1; 70861.103Skamil 70871.103Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 70881.103Skamil 70891.103Skamil if (masked) 70901.103Skamil kp_sigmask = kp.p_sigmask; 70911.103Skamil 70921.103Skamil if (ignored) 70931.103Skamil kp_sigignore = kp.p_sigignore; 70941.103Skamil 70951.103Skamil DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in " 70961.103Skamil "EVENT_MASK for the child %d\n", child); 70971.103Skamil event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE; 70981.103Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 70991.103Skamil 71001.103Skamil DPRINTF("Before resuming the child process where it left off and " 71011.103Skamil "without signal to be sent\n"); 71021.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 71031.103Skamil 71041.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 71051.103Skamil child); 71061.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 71071.103Skamil child); 71081.103Skamil 71091.103Skamil validate_status_stopped(status, SIGTRAP); 71101.103Skamil 71111.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 71121.103Skamil 71131.103Skamil if (masked) { 71141.103Skamil DPRINTF("kp_sigmask=" 71151.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71161.103Skamil PRIx32 "\n", 71171.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 71181.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 71191.103Skamil 71201.103Skamil DPRINTF("kp.p_sigmask=" 71211.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71221.103Skamil PRIx32 "\n", 71231.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 71241.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 71251.103Skamil 71261.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 71271.103Skamil sizeof(kp_sigmask))); 71281.103Skamil } 71291.103Skamil 71301.103Skamil if (ignored) { 71311.103Skamil DPRINTF("kp_sigignore=" 71321.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71331.103Skamil PRIx32 "\n", 71341.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 71351.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 71361.103Skamil 71371.103Skamil DPRINTF("kp.p_sigignore=" 71381.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71391.103Skamil PRIx32 "\n", 71401.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 71411.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 71421.103Skamil 71431.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 71441.103Skamil sizeof(kp_sigignore))); 71451.103Skamil } 71461.103Skamil 71471.103Skamil SYSCALL_REQUIRE( 71481.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 71491.103Skamil DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event, 71501.103Skamil child2); 71511.103Skamil if (!(flags & CLONE_VFORK)) { 71521.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 71531.103Skamil PTRACE_FORK); 71541.103Skamil } else { 71551.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 71561.103Skamil PTRACE_VFORK); 71571.103Skamil } 71581.103Skamil 71591.103Skamil child2 = state.pe_other_pid; 71601.103Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 71611.103Skamil 71621.103Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 71631.103Skamil "%d\n", TWAIT_FNAME, child2, child); 71641.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 71651.103Skamil child2); 71661.103Skamil 71671.103Skamil validate_status_stopped(status, SIGTRAP); 71681.103Skamil 71691.103Skamil name[3] = child2; 71701.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 71711.103Skamil 71721.103Skamil if (masked) { 71731.103Skamil DPRINTF("kp_sigmask=" 71741.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71751.103Skamil PRIx32 "\n", 71761.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 71771.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 71781.103Skamil 71791.103Skamil DPRINTF("kp.p_sigmask=" 71801.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71811.103Skamil PRIx32 "\n", 71821.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 71831.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 71841.103Skamil 71851.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 71861.103Skamil sizeof(kp_sigmask))); 71871.103Skamil } 71881.103Skamil 71891.103Skamil if (ignored) { 71901.103Skamil DPRINTF("kp_sigignore=" 71911.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71921.103Skamil PRIx32 "\n", 71931.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 71941.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 71951.103Skamil 71961.103Skamil DPRINTF("kp.p_sigignore=" 71971.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71981.103Skamil PRIx32 "\n", 71991.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 72001.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 72011.103Skamil 72021.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 72031.103Skamil sizeof(kp_sigignore))); 72041.103Skamil } 72051.103Skamil 72061.103Skamil SYSCALL_REQUIRE( 72071.103Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 72081.103Skamil if (!(flags & CLONE_VFORK)) { 72091.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 72101.103Skamil PTRACE_FORK); 72111.103Skamil } else { 72121.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 72131.103Skamil PTRACE_VFORK); 72141.103Skamil } 72151.103Skamil 72161.103Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 72171.103Skamil 72181.103Skamil DPRINTF("Before resuming the forkee process where it left off " 72191.103Skamil "and without signal to be sent\n"); 72201.103Skamil SYSCALL_REQUIRE( 72211.103Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 72221.103Skamil 72231.103Skamil DPRINTF("Before resuming the child process where it left off " 72241.103Skamil "and without signal to be sent\n"); 72251.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 72261.103Skamil 72271.103Skamil if (flags & CLONE_VFORK) { 72281.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 72291.103Skamil child); 72301.103Skamil TWAIT_REQUIRE_SUCCESS( 72311.103Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 72321.103Skamil 72331.103Skamil validate_status_stopped(status, SIGTRAP); 72341.103Skamil 72351.103Skamil name[3] = child; 72361.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 72371.103Skamil 72381.103Skamil /* 72391.103Skamil * SIGCHLD is now pending in the signal queue and 72401.103Skamil * the kernel presents it to userland as a masked signal. 72411.103Skamil */ 72421.103Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 72431.103Skamil 72441.103Skamil if (masked) { 72451.103Skamil DPRINTF("kp_sigmask=" 72461.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72471.103Skamil PRIx32 "\n", 72481.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 72491.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 72501.103Skamil 72511.103Skamil DPRINTF("kp.p_sigmask=" 72521.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72531.103Skamil PRIx32 "\n", 72541.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 72551.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 72561.103Skamil 72571.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 72581.103Skamil sizeof(kp_sigmask))); 72591.103Skamil } 72601.103Skamil 72611.103Skamil if (ignored) { 72621.103Skamil DPRINTF("kp_sigignore=" 72631.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72641.103Skamil PRIx32 "\n", 72651.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 72661.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 72671.103Skamil 72681.103Skamil DPRINTF("kp.p_sigignore=" 72691.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 72701.103Skamil PRIx32 "\n", 72711.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 72721.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 72731.103Skamil 72741.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 72751.103Skamil sizeof(kp_sigignore))); 72761.103Skamil } 72771.103Skamil 72781.103Skamil SYSCALL_REQUIRE( 72791.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 72801.103Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 72811.103Skamil 72821.103Skamil child2 = state.pe_other_pid; 72831.103Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 72841.103Skamil child2); 72851.103Skamil 72861.103Skamil DPRINTF("Before resuming the child process where it left off " 72871.103Skamil "and without signal to be sent\n"); 72881.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 72891.103Skamil } 72901.103Skamil 72911.103Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 72921.103Skamil "\n", TWAIT_FNAME); 72931.103Skamil TWAIT_REQUIRE_SUCCESS( 72941.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 72951.103Skamil 72961.103Skamil validate_status_exited(status, exitval2); 72971.103Skamil 72981.103Skamil DPRINTF("Before calling %s() for the forkee - expected no " 72991.103Skamil "process\n", TWAIT_FNAME); 73001.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 73011.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 73021.103Skamil 73031.103Skamil DPRINTF("Before calling %s() for the child - expected stopped " 73041.103Skamil "SIGCHLD\n", TWAIT_FNAME); 73051.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 73061.103Skamil 73071.103Skamil validate_status_stopped(status, SIGCHLD); 73081.103Skamil 73091.103Skamil DPRINTF("Before resuming the child process where it left off and " 73101.103Skamil "without signal to be sent\n"); 73111.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 73121.103Skamil 73131.103Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 73141.103Skamil TWAIT_FNAME); 73151.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 73161.103Skamil 73171.103Skamil validate_status_exited(status, exitval); 73181.103Skamil 73191.103Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 73201.103Skamil TWAIT_FNAME); 73211.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 73221.103Skamil} 73231.103Skamil 73241.106Skamil#define CLONE_TEST2(name,flags,masked,ignored) \ 73251.103SkamilATF_TC(name); \ 73261.103SkamilATF_TC_HEAD(name, tc) \ 73271.103Skamil{ \ 73281.103Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\ 73291.103Skamil " regardless of signal %s%s", \ 73301.103Skamil #flags, masked ? "masked" : "", ignored ? "ignored" : ""); \ 73311.103Skamil} \ 73321.103Skamil \ 73331.103SkamilATF_TC_BODY(name, tc) \ 73341.103Skamil{ \ 73351.103Skamil \ 73361.106Skamil clone_body2(flags, masked, ignored); \ 73371.103Skamil} 73381.103Skamil 73391.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false) 73401.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true) 73411.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false) 73421.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true) 73431.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false) 73441.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true) 73451.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false) 73461.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true) 73471.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX 73481.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true) // XXX 73491.110Skamil#if TEST_VFORK_ENABLED 73501.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false) 73511.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true) 73521.103Skamil#endif 73531.110Skamil#endif 73541.103Skamil 73551.103Skamil/// ---------------------------------------------------------------------------- 73561.103Skamil 73571.111Skamil#if TEST_VFORK_ENABLED 73581.107Skamil#if defined(TWAIT_HAVE_PID) 73591.107Skamilstatic void 73601.107Skamiltraceme_vfork_clone_body(int flags) 73611.107Skamil{ 73621.107Skamil const int exitval = 5; 73631.107Skamil const int exitval2 = 15; 73641.107Skamil pid_t child, child2 = 0, wpid; 73651.107Skamil#if defined(TWAIT_HAVE_STATUS) 73661.107Skamil int status; 73671.107Skamil#endif 73681.107Skamil 73691.107Skamil const size_t stack_size = 1024 * 1024; 73701.107Skamil void *stack, *stack_base; 73711.107Skamil 73721.107Skamil stack = malloc(stack_size); 73731.107Skamil ATF_REQUIRE(stack != NULL); 73741.107Skamil 73751.107Skamil#ifdef __MACHINE_STACK_GROWS_UP 73761.107Skamil stack_base = stack; 73771.107Skamil#else 73781.107Skamil stack_base = (char *)stack + stack_size; 73791.107Skamil#endif 73801.107Skamil 73811.107Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 73821.107Skamil if (child == 0) { 73831.107Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 73841.107Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 73851.107Skamil 73861.107Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 73871.107Skamil flags); 73881.107Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 73891.107Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 73901.107Skamil 73911.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 73921.107Skamil child2); 73931.107Skamil 73941.107Skamil // XXX WALLSIG? 73951.107Skamil FORKEE_REQUIRE_SUCCESS 73961.107Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 73971.107Skamil 73981.107Skamil forkee_status_exited(status, exitval2); 73991.107Skamil 74001.107Skamil DPRINTF("Before exiting of the child process\n"); 74011.107Skamil _exit(exitval); 74021.107Skamil } 74031.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 74041.107Skamil 74051.107Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 74061.107Skamil TWAIT_FNAME); 74071.107Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74081.107Skamil 74091.107Skamil validate_status_exited(status, exitval); 74101.107Skamil 74111.107Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 74121.107Skamil TWAIT_FNAME); 74131.107Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 74141.107Skamil} 74151.107Skamil 74161.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags) \ 74171.107SkamilATF_TC(name); \ 74181.107SkamilATF_TC_HEAD(name, tc) \ 74191.107Skamil{ \ 74201.107Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is " \ 74211.107Skamil "handled correctly with vfork(2)ed tracer", \ 74221.107Skamil #flags); \ 74231.107Skamil} \ 74241.107Skamil \ 74251.107SkamilATF_TC_BODY(name, tc) \ 74261.107Skamil{ \ 74271.107Skamil \ 74281.107Skamil traceme_vfork_clone_body(flags); \ 74291.107Skamil} 74301.107Skamil 74311.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0) 74321.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM) 74331.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS) 74341.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES) 74351.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND) // XXX 74361.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK) 74371.107Skamil#endif 74381.110Skamil#endif 74391.107Skamil 74401.107Skamil/// ---------------------------------------------------------------------------- 74411.107Skamil 74421.122Skamilstatic void 74431.122Skamiluser_va0_disable(int operation) 74441.122Skamil{ 74451.122Skamil pid_t child, wpid; 74461.122Skamil#if defined(TWAIT_HAVE_STATUS) 74471.122Skamil int status; 74481.122Skamil#endif 74491.122Skamil const int sigval = SIGSTOP; 74501.122Skamil int rv; 74511.122Skamil 74521.122Skamil struct ptrace_siginfo info; 74531.122Skamil 74541.122Skamil if (get_user_va0_disable() == 0) 74551.122Skamil atf_tc_skip("vm.user_va0_disable is set to 0"); 74561.122Skamil 74571.122Skamil memset(&info, 0, sizeof(info)); 74581.122Skamil 74591.122Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 74601.122Skamil SYSCALL_REQUIRE((child = fork()) != -1); 74611.122Skamil if (child == 0) { 74621.122Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 74631.122Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 74641.122Skamil 74651.122Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 74661.122Skamil FORKEE_ASSERT(raise(sigval) == 0); 74671.122Skamil 74681.122Skamil /* NOTREACHED */ 74691.122Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 74701.122Skamil __unreachable(); 74711.122Skamil } 74721.122Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 74731.122Skamil 74741.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 74751.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 74761.122Skamil 74771.122Skamil validate_status_stopped(status, sigval); 74781.122Skamil 74791.122Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 74801.122Skamil "child\n"); 74811.122Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 74821.122Skamil sizeof(info)) != -1); 74831.122Skamil 74841.122Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 74851.122Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 74861.122Skamil "si_errno=%#x\n", 74871.122Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 74881.122Skamil info.psi_siginfo.si_errno); 74891.122Skamil 74901.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 74911.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 74921.122Skamil 74931.122Skamil DPRINTF("Before resuming the child process in PC=0x0 " 74941.122Skamil "and without signal to be sent\n"); 74951.122Skamil errno = 0; 74961.122Skamil rv = ptrace(operation, child, (void *)0, 0); 74971.122Skamil ATF_REQUIRE_EQ(errno, EINVAL); 74981.122Skamil ATF_REQUIRE_EQ(rv, -1); 74991.122Skamil 75001.122Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 75011.122Skamil 75021.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75031.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 75041.122Skamil validate_status_signaled(status, SIGKILL, 0); 75051.122Skamil 75061.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 75071.122Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 75081.122Skamil} 75091.122Skamil 75101.122Skamil#define USER_VA0_DISABLE(test, operation) \ 75111.122SkamilATF_TC(test); \ 75121.122SkamilATF_TC_HEAD(test, tc) \ 75131.122Skamil{ \ 75141.122Skamil atf_tc_set_md_var(tc, "descr", \ 75151.122Skamil "Verify behavior of " #operation " with PC set to 0x0"); \ 75161.122Skamil} \ 75171.122Skamil \ 75181.122SkamilATF_TC_BODY(test, tc) \ 75191.122Skamil{ \ 75201.122Skamil \ 75211.122Skamil user_va0_disable(operation); \ 75221.122Skamil} 75231.122Skamil 75241.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE) 75251.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL) 75261.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH) 75271.122Skamil 75281.122Skamil/// ---------------------------------------------------------------------------- 75291.122Skamil 75301.1Skamil#include "t_ptrace_amd64_wait.h" 75311.1Skamil#include "t_ptrace_i386_wait.h" 75321.1Skamil#include "t_ptrace_x86_wait.h" 75331.1Skamil 75341.1SkamilATF_TP_ADD_TCS(tp) 75351.1Skamil{ 75361.1Skamil setvbuf(stdout, NULL, _IONBF, 0); 75371.1Skamil setvbuf(stderr, NULL, _IONBF, 0); 75381.33Skamil 75391.36Skamil ATF_TP_ADD_TC(tp, traceme_raise1); 75401.33Skamil ATF_TP_ADD_TC(tp, traceme_raise2); 75411.33Skamil ATF_TP_ADD_TC(tp, traceme_raise3); 75421.33Skamil ATF_TP_ADD_TC(tp, traceme_raise4); 75431.33Skamil ATF_TP_ADD_TC(tp, traceme_raise5); 75441.85Skamil ATF_TP_ADD_TC(tp, traceme_raise6); 75451.85Skamil ATF_TP_ADD_TC(tp, traceme_raise7); 75461.85Skamil ATF_TP_ADD_TC(tp, traceme_raise8); 75471.85Skamil ATF_TP_ADD_TC(tp, traceme_raise9); 75481.85Skamil ATF_TP_ADD_TC(tp, traceme_raise10); 75491.33Skamil 75501.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1); 75511.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2); 75521.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3); 75531.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4); 75541.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5); 75551.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6); 75561.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7); 75571.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8); 75581.87Skamil 75591.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1); 75601.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2); 75611.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3); 75621.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4); 75631.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5); 75641.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6); 75651.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7); 75661.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8); 75671.86Skamil 75681.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_trap); 75691.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_segv); 75701.71Skamil ATF_TP_ADD_TC(tp, traceme_crash_ill); 75711.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_fpe); 75721.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_bus); 75731.59Skamil 75741.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap); 75751.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv); 75761.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill); 75771.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe); 75781.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus); 75791.88Skamil 75801.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap); 75811.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv); 75821.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill); 75831.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe); 75841.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus); 75851.88Skamil 75861.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1); 75871.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2); 75881.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3); 75891.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4); 75901.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5); 75911.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6); 75921.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7); 75931.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8); 75941.50Skamil 75951.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1); 75961.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2); 75971.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3); 75981.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4); 75991.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5); 76001.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6); 76011.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7); 76021.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8); 76031.50Skamil 76041.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1); 76051.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2); 76061.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3); 76071.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4); 76081.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5); 76091.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6); 76101.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7); 76111.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8); 76121.50Skamil 76131.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1); 76141.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2); 76151.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3); 76161.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4); 76171.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5); 76181.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6); 76191.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7); 76201.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8); 76211.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9); 76221.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10); 76231.1Skamil 76241.37Skamil ATF_TP_ADD_TC(tp, traceme_pid1_parent); 76251.37Skamil 76261.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise1); 76271.46Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise2); 76281.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise3); 76291.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise4); 76301.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise5); 76311.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise6); 76321.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise7); 76331.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise8); 76341.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise9); 76351.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise10); 76361.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise11); 76371.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise12); 76381.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise13); 76391.40Skamil 76401.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap); 76411.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv); 76421.71Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill); 76431.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe); 76441.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus); 76451.41Skamil 76461.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap); 76471.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv); 76481.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill); 76491.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe); 76501.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus); 76511.92Skamil 76521.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap); 76531.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv); 76541.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill); 76551.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe); 76561.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus); 76571.92Skamil 76581.43Skamil ATF_TP_ADD_TC(tp, traceme_vfork_exec); 76591.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec); 76601.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec); 76611.43Skamil 76621.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap); 76631.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv); 76641.71Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill); 76651.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe); 76661.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus); 76671.59Skamil 76681.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 76691.94Skamil unrelated_tracer_sees_signalmasked_crash_trap); 76701.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 76711.94Skamil unrelated_tracer_sees_signalmasked_crash_segv); 76721.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 76731.94Skamil unrelated_tracer_sees_signalmasked_crash_ill); 76741.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 76751.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe); 76761.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 76771.94Skamil unrelated_tracer_sees_signalmasked_crash_bus); 76781.94Skamil 76791.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 76801.94Skamil unrelated_tracer_sees_signalignored_crash_trap); 76811.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 76821.94Skamil unrelated_tracer_sees_signalignored_crash_segv); 76831.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 76841.94Skamil unrelated_tracer_sees_signalignored_crash_ill); 76851.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 76861.94Skamil unrelated_tracer_sees_signalignored_crash_fpe); 76871.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 76881.94Skamil unrelated_tracer_sees_signalignored_crash_bus); 76891.94Skamil 76901.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent); 76911.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates); 76921.61Skre ATF_TP_ADD_TC_HAVE_PID(tp, 76931.61Skre unrelated_tracer_sees_terminaton_before_the_parent); 76941.67Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process); 76951.51Skamil 76961.51Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_child); 76971.66Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child); 76981.51Skamil 76991.51Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_parent); 77001.65Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent); 77011.51Skamil 77021.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77031.51Skamil tracee_sees_its_original_parent_getppid); 77041.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77051.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2); 77061.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 77071.51Skamil tracee_sees_its_original_parent_procfs_status); 77081.1Skamil 77091.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_empty); 77101.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_fork); 77111.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork); 77121.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done); 77131.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create); 77141.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit); 77151.1Skamil 77161.31Skamil ATF_TP_ADD_TC(tp, fork1); 77171.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork2); 77181.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork3); 77191.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork4); 77201.31Skamil ATF_TP_ADD_TC(tp, fork5); 77211.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork6); 77221.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork7); 77231.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork8); 77241.31Skamil 77251.109Skamil#if TEST_VFORK_ENABLED 77261.31Skamil ATF_TP_ADD_TC(tp, vfork1); 77271.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork2); 77281.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork3); 77291.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork4); 77301.31Skamil ATF_TP_ADD_TC(tp, vfork5); 77311.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork6); 77321.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork7); 77331.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork8); 77341.116Skamil#endif 77351.1Skamil 77361.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_detach_forker); 77371.116Skamil#if TEST_VFORK_ENABLED 77381.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforker); 77391.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_detach_vforkerdone); 77401.116Skamil#endif 77411.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_kill_forker); 77421.116Skamil#if TEST_VFORK_ENABLED 77431.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforker); 77441.116Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_kill_vforkerdone); 77451.116Skamil#endif 77461.116Skamil 77471.116Skamil#if TEST_VFORK_ENABLED 77481.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_fork); 77491.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_vfork); 77501.109Skamil#endif 77511.108Skamil 77521.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8); 77531.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16); 77541.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32); 77551.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64); 77561.54Skamil 77571.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8); 77581.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16); 77591.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32); 77601.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64); 77611.54Skamil 77621.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8); 77631.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16); 77641.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32); 77651.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64); 77661.54Skamil 77671.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8); 77681.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16); 77691.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32); 77701.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64); 77711.54Skamil 77721.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d); 77731.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i); 77741.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d); 77751.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i); 77761.54Skamil 77771.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text); 77781.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text); 77791.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text); 77801.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text); 77811.54Skamil 77821.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text); 77831.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text); 77841.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text); 77851.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text); 77861.54Skamil 77871.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text); 77881.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text); 77891.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text); 77901.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text); 77911.54Skamil 77921.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text); 77931.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text); 77941.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text); 77951.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text); 77961.54Skamil 77971.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text); 77981.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text); 77991.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text); 78001.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text); 78011.1Skamil 78021.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv); 78031.1Skamil 78041.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i); 78051.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d); 78061.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i); 78071.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d); 78081.101Skamil 78091.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i); 78101.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d); 78111.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i); 78121.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d); 78131.101Skamil 78141.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv); 78151.101Skamil 78161.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i); 78171.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d); 78181.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i); 78191.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d); 78201.115Skamil 78211.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i); 78221.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d); 78231.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i); 78241.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d); 78251.115Skamil 78261.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1); 78271.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2); 78281.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3); 78291.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4); 78301.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5); 78311.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6); 78321.1Skamil 78331.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1); 78341.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2); 78351.1Skamil 78361.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step1); 78371.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step2); 78381.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step3); 78391.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step4); 78401.1Skamil 78411.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep1); 78421.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep2); 78431.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep3); 78441.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep4); 78451.2Skamil 78461.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked); 78471.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored); 78481.95Skamil 78491.1Skamil ATF_TP_ADD_TC(tp, kill1); 78501.1Skamil ATF_TP_ADD_TC(tp, kill2); 78511.75Skamil ATF_TP_ADD_TC(tp, kill3); 78521.1Skamil 78531.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0); 78541.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1); 78551.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2); 78561.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3); 78571.77Skamil 78581.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0); 78591.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1); 78601.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2); 78611.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3); 78621.1Skamil 78631.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_unmodified); 78641.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_faked); 78651.79Skamil 78661.82Skamil ATF_TP_ADD_TC(tp, traceme_exec); 78671.97Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_exec); 78681.97Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_exec); 78691.1Skamil 78701.119Skamil ATF_TP_ADD_TC(tp, trace_thread_nolwpevents); 78711.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpexit); 78721.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate); 78731.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit); 78741.1Skamil 78751.84Skamil ATF_TP_ADD_TC(tp, signal_mask_unrelated); 78761.84Skamil 78771.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked); 78781.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored); 78791.109Skamil#if TEST_VFORK_ENABLED 78801.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked); 78811.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored); 78821.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked); 78831.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored); 78841.109Skamil#endif 78851.99Skamil 78861.1Skamil ATF_TP_ADD_TC(tp, signal9); 78871.1Skamil ATF_TP_ADD_TC(tp, signal10); 78881.1Skamil 78891.1Skamil ATF_TP_ADD_TC(tp, suspend1); 78901.1Skamil ATF_TP_ADD_TC(tp, suspend2); 78911.1Skamil 78921.1Skamil ATF_TP_ADD_TC(tp, resume1); 78931.1Skamil 78941.1Skamil ATF_TP_ADD_TC(tp, syscall1); 78951.1Skamil 78961.1Skamil ATF_TP_ADD_TC(tp, syscallemu1); 78971.1Skamil 78981.106Skamil ATF_TP_ADD_TC(tp, clone1); 78991.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone2); 79001.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone3); 79011.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone4); 79021.106Skamil ATF_TP_ADD_TC(tp, clone5); 79031.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone6); 79041.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone7); 79051.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone8); 79061.106Skamil 79071.106Skamil ATF_TP_ADD_TC(tp, clone_vm1); 79081.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2); 79091.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3); 79101.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4); 79111.106Skamil ATF_TP_ADD_TC(tp, clone_vm5); 79121.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6); 79131.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7); 79141.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8); 79151.106Skamil 79161.106Skamil ATF_TP_ADD_TC(tp, clone_fs1); 79171.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2); 79181.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3); 79191.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4); 79201.106Skamil ATF_TP_ADD_TC(tp, clone_fs5); 79211.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6); 79221.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7); 79231.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8); 79241.106Skamil 79251.106Skamil ATF_TP_ADD_TC(tp, clone_files1); 79261.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2); 79271.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3); 79281.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4); 79291.106Skamil ATF_TP_ADD_TC(tp, clone_files5); 79301.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6); 79311.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7); 79321.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8); 79331.106Skamil 79341.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand1); // XXX 79351.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX 79361.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX 79371.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX 79381.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand5); // XXX 79391.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX 79401.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX 79411.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX 79421.106Skamil 79431.109Skamil#if TEST_VFORK_ENABLED 79441.106Skamil ATF_TP_ADD_TC(tp, clone_vfork1); 79451.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2); 79461.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3); 79471.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4); 79481.106Skamil ATF_TP_ADD_TC(tp, clone_vfork5); 79491.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6); 79501.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7); 79511.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8); 79521.109Skamil#endif 79531.106Skamil 79541.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored); 79551.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked); 79561.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored); 79571.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked); 79581.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored); 79591.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked); 79601.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored); 79611.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked); 79621.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX 79631.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX 79641.109Skamil#if TEST_VFORK_ENABLED 79651.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored); 79661.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked); 79671.109Skamil#endif 79681.103Skamil 79691.109Skamil#if TEST_VFORK_ENABLED 79701.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone); 79711.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm); 79721.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs); 79731.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files); 79741.107Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX 79751.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork); 79761.109Skamil#endif 79771.107Skamil 79781.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue); 79791.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall); 79801.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach); 79811.122Skamil 79821.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64(); 79831.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_I386(); 79841.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_X86(); 79851.1Skamil 79861.1Skamil return atf_no_error(); 79871.1Skamil} 7988