t_ptrace_wait.c revision 1.115
11.115Skamil/* $NetBSD: t_ptrace_wait.c,v 1.115 2019/04/30 22:39:31 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.115Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.115 2019/04/30 22:39:31 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.1Skamil#include <atf-c.h> 621.1Skamil 631.1Skamil#include "h_macros.h" 641.1Skamil 651.1Skamil#include "t_ptrace_wait.h" 661.1Skamil#include "msg.h" 671.1Skamil 681.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \ 691.61Skre SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \ 701.61Skre sizeof(msg)) == 0) 711.1Skamil 721.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \ 731.61Skre FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \ 741.61Skre sizeof(msg)) == 0) 751.1Skamil 761.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \ 771.61Skre FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \ 781.61Skre sizeof(msg)) == 0) 791.1Skamil 801.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \ 811.61Skre SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \ 821.61Skre sizeof(msg)) == 0) 831.13Schristos 841.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \ 851.13Schristos strerror(errno)) 861.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \ 871.18Schristos "%d(%s) != %d", res, strerror(res), exp) 881.13Schristos 891.13Schristosstatic int debug = 0; 901.13Schristos 911.13Schristos#define DPRINTF(a, ...) do \ 921.13Schristos if (debug) printf(a, ##__VA_ARGS__); \ 931.13Schristos while (/*CONSTCOND*/0) 941.1Skamil 951.110Skamil#ifndef TEST_VFORK_ENABLED 961.109Skamil#define TEST_VFORK_ENABLED 0 971.110Skamil#endif 981.109Skamil 991.34Skamil/// ---------------------------------------------------------------------------- 1001.34Skamil 1011.33Skamilstatic void 1021.33Skamiltraceme_raise(int sigval) 1031.1Skamil{ 1041.1Skamil const int exitval = 5; 1051.1Skamil pid_t child, wpid; 1061.1Skamil#if defined(TWAIT_HAVE_STATUS) 1071.1Skamil int status; 1081.1Skamil#endif 1091.1Skamil 1101.45Skamil struct ptrace_siginfo info; 1111.45Skamil memset(&info, 0, sizeof(info)); 1121.45Skamil 1131.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 1141.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 1151.1Skamil if (child == 0) { 1161.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1171.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1181.1Skamil 1191.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1201.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 1211.1Skamil 1221.36Skamil switch (sigval) { 1231.36Skamil case SIGKILL: 1241.36Skamil /* NOTREACHED */ 1251.36Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 1261.70Smrg __unreachable(); 1271.36Skamil default: 1281.36Skamil DPRINTF("Before exiting of the child process\n"); 1291.36Skamil _exit(exitval); 1301.36Skamil } 1311.1Skamil } 1321.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1331.1Skamil 1341.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1351.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1361.1Skamil 1371.36Skamil switch (sigval) { 1381.36Skamil case SIGKILL: 1391.36Skamil validate_status_signaled(status, sigval, 0); 1401.36Skamil break; 1411.36Skamil default: 1421.36Skamil validate_status_stopped(status, sigval); 1431.1Skamil 1441.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 1451.61Skre "child\n"); 1461.45Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 1471.61Skre sizeof(info)) != -1); 1481.45Skamil 1491.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1501.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 1511.61Skre "si_errno=%#x\n", 1521.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1531.61Skre info.psi_siginfo.si_errno); 1541.45Skamil 1551.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 1561.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 1571.45Skamil 1581.36Skamil DPRINTF("Before resuming the child process where it left off " 1591.36Skamil "and without signal to be sent\n"); 1601.36Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1611.1Skamil 1621.36Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1631.36Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 1641.61Skre child); 1651.36Skamil break; 1661.36Skamil } 1671.1Skamil 1681.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1691.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 1701.1Skamil} 1711.1Skamil 1721.61Skre#define TRACEME_RAISE(test, sig) \ 1731.61SkreATF_TC(test); \ 1741.61SkreATF_TC_HEAD(test, tc) \ 1751.61Skre{ \ 1761.61Skre atf_tc_set_md_var(tc, "descr", \ 1771.61Skre "Verify " #sig " followed by _exit(2) in a child"); \ 1781.61Skre} \ 1791.61Skre \ 1801.61SkreATF_TC_BODY(test, tc) \ 1811.61Skre{ \ 1821.61Skre \ 1831.61Skre traceme_raise(sig); \ 1841.33Skamil} 1851.33Skamil 1861.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */ 1871.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */ 1881.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */ 1891.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP) /* hangup */ 1901.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */ 1911.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */ 1921.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */ 1931.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */ 1941.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */ 1951.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */ 1961.33Skamil 1971.34Skamil/// ---------------------------------------------------------------------------- 1981.1Skamil 1991.1Skamilstatic void 2001.87Skamiltraceme_raisesignal_ignored(int sigignored) 2011.87Skamil{ 2021.87Skamil const int exitval = 5; 2031.87Skamil const int sigval = SIGSTOP; 2041.87Skamil pid_t child, wpid; 2051.87Skamil struct sigaction sa; 2061.87Skamil#if defined(TWAIT_HAVE_STATUS) 2071.87Skamil int status; 2081.87Skamil#endif 2091.87Skamil struct ptrace_siginfo info; 2101.87Skamil 2111.87Skamil memset(&info, 0, sizeof(info)); 2121.87Skamil 2131.87Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 2141.87Skamil SYSCALL_REQUIRE((child = fork()) != -1); 2151.87Skamil if (child == 0) { 2161.87Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2171.87Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2181.87Skamil 2191.87Skamil memset(&sa, 0, sizeof(sa)); 2201.87Skamil sa.sa_handler = SIG_IGN; 2211.87Skamil sigemptyset(&sa.sa_mask); 2221.87Skamil FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1); 2231.87Skamil 2241.87Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 2251.87Skamil FORKEE_ASSERT(raise(sigval) == 0); 2261.87Skamil 2271.87Skamil DPRINTF("Before raising %s from child\n", 2281.87Skamil strsignal(sigignored)); 2291.87Skamil FORKEE_ASSERT(raise(sigignored) == 0); 2301.87Skamil 2311.87Skamil DPRINTF("Before exiting of the child process\n"); 2321.87Skamil _exit(exitval); 2331.87Skamil } 2341.87Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2351.87Skamil 2361.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2371.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2381.87Skamil 2391.87Skamil validate_status_stopped(status, sigval); 2401.87Skamil 2411.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2421.87Skamil SYSCALL_REQUIRE( 2431.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2441.87Skamil 2451.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2461.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2471.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2481.87Skamil info.psi_siginfo.si_errno); 2491.87Skamil 2501.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 2511.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2521.87Skamil 2531.87Skamil DPRINTF("Before resuming the child process where it left off and " 2541.87Skamil "without signal to be sent\n"); 2551.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2561.87Skamil 2571.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2581.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2591.87Skamil 2601.87Skamil validate_status_stopped(status, sigignored); 2611.87Skamil 2621.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2631.87Skamil SYSCALL_REQUIRE( 2641.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2651.87Skamil 2661.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2671.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2681.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2691.87Skamil info.psi_siginfo.si_errno); 2701.87Skamil 2711.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored); 2721.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2731.87Skamil 2741.87Skamil DPRINTF("Before resuming the child process where it left off and " 2751.87Skamil "without signal to be sent\n"); 2761.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2771.87Skamil 2781.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2791.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2801.87Skamil 2811.87Skamil validate_status_exited(status, exitval); 2821.87Skamil 2831.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2841.87Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 2851.87Skamil} 2861.87Skamil 2871.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig) \ 2881.87SkamilATF_TC(test); \ 2891.87SkamilATF_TC_HEAD(test, tc) \ 2901.87Skamil{ \ 2911.87Skamil atf_tc_set_md_var(tc, "descr", \ 2921.87Skamil "Verify that ignoring (with SIG_IGN) " #sig " in tracee " \ 2931.87Skamil "does not stop tracer from catching this raised signal"); \ 2941.87Skamil} \ 2951.87Skamil \ 2961.87SkamilATF_TC_BODY(test, tc) \ 2971.87Skamil{ \ 2981.87Skamil \ 2991.87Skamil traceme_raisesignal_ignored(sig); \ 3001.87Skamil} 3011.87Skamil 3021.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 3031.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */ 3041.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP) /* hangup */ 3051.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */ 3061.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */ 3071.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */ 3081.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */ 3091.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */ 3101.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */ 3111.87Skamil 3121.87Skamil/// ---------------------------------------------------------------------------- 3131.87Skamil 3141.87Skamilstatic void 3151.86Skamiltraceme_raisesignal_masked(int sigmasked) 3161.86Skamil{ 3171.86Skamil const int exitval = 5; 3181.86Skamil const int sigval = SIGSTOP; 3191.86Skamil pid_t child, wpid; 3201.86Skamil#if defined(TWAIT_HAVE_STATUS) 3211.86Skamil int status; 3221.86Skamil#endif 3231.86Skamil sigset_t intmask; 3241.86Skamil struct ptrace_siginfo info; 3251.86Skamil 3261.86Skamil memset(&info, 0, sizeof(info)); 3271.86Skamil 3281.86Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 3291.86Skamil SYSCALL_REQUIRE((child = fork()) != -1); 3301.86Skamil if (child == 0) { 3311.86Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 3321.86Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 3331.86Skamil 3341.86Skamil sigemptyset(&intmask); 3351.86Skamil sigaddset(&intmask, sigmasked); 3361.86Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 3371.86Skamil 3381.86Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 3391.86Skamil FORKEE_ASSERT(raise(sigval) == 0); 3401.86Skamil 3411.86Skamil DPRINTF("Before raising %s breakpoint from child\n", 3421.86Skamil strsignal(sigmasked)); 3431.86Skamil FORKEE_ASSERT(raise(sigmasked) == 0); 3441.86Skamil 3451.86Skamil DPRINTF("Before exiting of the child process\n"); 3461.86Skamil _exit(exitval); 3471.86Skamil } 3481.86Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 3491.86Skamil 3501.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3511.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3521.86Skamil 3531.86Skamil validate_status_stopped(status, sigval); 3541.86Skamil 3551.86Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 3561.86Skamil SYSCALL_REQUIRE( 3571.86Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 3581.86Skamil 3591.86Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 3601.86Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 3611.86Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 3621.86Skamil info.psi_siginfo.si_errno); 3631.86Skamil 3641.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 3651.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 3661.86Skamil 3671.86Skamil DPRINTF("Before resuming the child process where it left off and " 3681.86Skamil "without signal to be sent\n"); 3691.86Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 3701.86Skamil 3711.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3721.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3731.86Skamil 3741.86Skamil validate_status_exited(status, exitval); 3751.86Skamil 3761.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3771.86Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 3781.86Skamil} 3791.86Skamil 3801.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig) \ 3811.86SkamilATF_TC(test); \ 3821.86SkamilATF_TC_HEAD(test, tc) \ 3831.86Skamil{ \ 3841.86Skamil atf_tc_set_md_var(tc, "descr", \ 3851.86Skamil "Verify that masking (with SIG_BLOCK) " #sig " in tracee " \ 3861.86Skamil "stops tracer from catching this raised signal"); \ 3871.86Skamil} \ 3881.86Skamil \ 3891.86SkamilATF_TC_BODY(test, tc) \ 3901.86Skamil{ \ 3911.86Skamil \ 3921.86Skamil traceme_raisesignal_masked(sig); \ 3931.86Skamil} 3941.86Skamil 3951.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 3961.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */ 3971.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP) /* hangup */ 3981.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */ 3991.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */ 4001.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */ 4011.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */ 4021.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */ 4031.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */ 4041.86Skamil 4051.86Skamil/// ---------------------------------------------------------------------------- 4061.86Skamil 4071.86Skamilstatic void 4081.59Skamiltraceme_crash(int sig) 4091.59Skamil{ 4101.59Skamil pid_t child, wpid; 4111.59Skamil#if defined(TWAIT_HAVE_STATUS) 4121.59Skamil int status; 4131.59Skamil#endif 4141.59Skamil struct ptrace_siginfo info; 4151.61Skre 4161.71Skamil#ifndef PTRACE_ILLEGAL_ASM 4171.71Skamil if (sig == SIGILL) 4181.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 4191.71Skamil#endif 4201.71Skamil 4211.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 4221.114Skamil atf_tc_skip("FP exceptions are not supported"); 4231.114Skamil 4241.59Skamil memset(&info, 0, sizeof(info)); 4251.59Skamil 4261.59Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 4271.59Skamil SYSCALL_REQUIRE((child = fork()) != -1); 4281.59Skamil if (child == 0) { 4291.59Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 4301.59Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 4311.59Skamil 4321.59Skamil DPRINTF("Before executing a trap\n"); 4331.59Skamil switch (sig) { 4341.59Skamil case SIGTRAP: 4351.59Skamil trigger_trap(); 4361.59Skamil break; 4371.59Skamil case SIGSEGV: 4381.59Skamil trigger_segv(); 4391.59Skamil break; 4401.59Skamil case SIGILL: 4411.59Skamil trigger_ill(); 4421.59Skamil break; 4431.59Skamil case SIGFPE: 4441.59Skamil trigger_fpe(); 4451.59Skamil break; 4461.59Skamil case SIGBUS: 4471.59Skamil trigger_bus(); 4481.59Skamil break; 4491.59Skamil default: 4501.59Skamil /* NOTREACHED */ 4511.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4521.59Skamil } 4531.59Skamil 4541.59Skamil /* NOTREACHED */ 4551.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4561.59Skamil } 4571.59Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 4581.59Skamil 4591.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4601.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4611.59Skamil 4621.59Skamil validate_status_stopped(status, sig); 4631.59Skamil 4641.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 4651.61Skre SYSCALL_REQUIRE( 4661.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 4671.59Skamil 4681.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 4691.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 4701.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 4711.61Skre info.psi_siginfo.si_errno); 4721.59Skamil 4731.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 4741.59Skamil switch (sig) { 4751.59Skamil case SIGTRAP: 4761.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 4771.59Skamil break; 4781.59Skamil case SIGSEGV: 4791.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 4801.59Skamil break; 4811.71Skamil case SIGILL: 4821.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 4831.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 4841.71Skamil break; 4851.59Skamil case SIGFPE: 4861.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 4871.59Skamil break; 4881.59Skamil case SIGBUS: 4891.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 4901.59Skamil break; 4911.59Skamil } 4921.59Skamil 4931.59Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 4941.59Skamil 4951.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4961.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4971.59Skamil 4981.59Skamil validate_status_signaled(status, SIGKILL, 0); 4991.59Skamil 5001.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5011.59Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 5021.59Skamil} 5031.59Skamil 5041.61Skre#define TRACEME_CRASH(test, sig) \ 5051.61SkreATF_TC(test); \ 5061.61SkreATF_TC_HEAD(test, tc) \ 5071.61Skre{ \ 5081.61Skre atf_tc_set_md_var(tc, "descr", \ 5091.61Skre "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \ 5101.61Skre} \ 5111.61Skre \ 5121.61SkreATF_TC_BODY(test, tc) \ 5131.61Skre{ \ 5141.61Skre \ 5151.61Skre traceme_crash(sig); \ 5161.59Skamil} 5171.59Skamil 5181.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP) 5191.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV) 5201.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL) 5211.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE) 5221.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS) 5231.59Skamil 5241.59Skamil/// ---------------------------------------------------------------------------- 5251.59Skamil 5261.59Skamilstatic void 5271.88Skamiltraceme_signalmasked_crash(int sig) 5281.88Skamil{ 5291.89Skamil const int sigval = SIGSTOP; 5301.88Skamil pid_t child, wpid; 5311.88Skamil#if defined(TWAIT_HAVE_STATUS) 5321.88Skamil int status; 5331.88Skamil#endif 5341.88Skamil struct ptrace_siginfo info; 5351.88Skamil sigset_t intmask; 5361.89Skamil struct kinfo_proc2 kp; 5371.89Skamil size_t len = sizeof(kp); 5381.89Skamil 5391.89Skamil int name[6]; 5401.89Skamil const size_t namelen = __arraycount(name); 5411.89Skamil ki_sigset_t kp_sigmask; 5421.88Skamil 5431.88Skamil#ifndef PTRACE_ILLEGAL_ASM 5441.88Skamil if (sig == SIGILL) 5451.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 5461.88Skamil#endif 5471.88Skamil 5481.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 5491.114Skamil atf_tc_skip("FP exceptions are not supported"); 5501.114Skamil 5511.88Skamil memset(&info, 0, sizeof(info)); 5521.88Skamil 5531.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 5541.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 5551.88Skamil if (child == 0) { 5561.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 5571.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 5581.88Skamil 5591.88Skamil sigemptyset(&intmask); 5601.88Skamil sigaddset(&intmask, sig); 5611.88Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 5621.88Skamil 5631.89Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 5641.89Skamil FORKEE_ASSERT(raise(sigval) == 0); 5651.89Skamil 5661.88Skamil DPRINTF("Before executing a trap\n"); 5671.88Skamil switch (sig) { 5681.88Skamil case SIGTRAP: 5691.88Skamil trigger_trap(); 5701.88Skamil break; 5711.88Skamil case SIGSEGV: 5721.88Skamil trigger_segv(); 5731.88Skamil break; 5741.88Skamil case SIGILL: 5751.88Skamil trigger_ill(); 5761.88Skamil break; 5771.88Skamil case SIGFPE: 5781.88Skamil trigger_fpe(); 5791.88Skamil break; 5801.88Skamil case SIGBUS: 5811.88Skamil trigger_bus(); 5821.88Skamil break; 5831.88Skamil default: 5841.88Skamil /* NOTREACHED */ 5851.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 5861.88Skamil } 5871.88Skamil 5881.88Skamil /* NOTREACHED */ 5891.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 5901.88Skamil } 5911.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 5921.88Skamil 5931.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5941.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 5951.88Skamil 5961.89Skamil validate_status_stopped(status, sigval); 5971.89Skamil 5981.89Skamil name[0] = CTL_KERN, 5991.89Skamil name[1] = KERN_PROC2, 6001.89Skamil name[2] = KERN_PROC_PID; 6011.89Skamil name[3] = child; 6021.89Skamil name[4] = sizeof(kp); 6031.89Skamil name[5] = 1; 6041.89Skamil 6051.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6061.89Skamil 6071.89Skamil kp_sigmask = kp.p_sigmask; 6081.89Skamil 6091.89Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 6101.89Skamil SYSCALL_REQUIRE( 6111.89Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6121.89Skamil 6131.89Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6141.89Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6151.89Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6161.89Skamil info.psi_siginfo.si_errno); 6171.89Skamil 6181.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 6191.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 6201.89Skamil 6211.89Skamil DPRINTF("Before resuming the child process where it left off and " 6221.89Skamil "without signal to be sent\n"); 6231.89Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 6241.89Skamil 6251.89Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6261.89Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6271.89Skamil 6281.88Skamil validate_status_stopped(status, sig); 6291.88Skamil 6301.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 6311.88Skamil SYSCALL_REQUIRE( 6321.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6331.88Skamil 6341.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6351.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6361.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6371.88Skamil info.psi_siginfo.si_errno); 6381.88Skamil 6391.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6401.89Skamil 6411.89Skamil DPRINTF("kp_sigmask=" 6421.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6431.89Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2], 6441.89Skamil kp_sigmask.__bits[3]); 6451.89Skamil 6461.89Skamil DPRINTF("kp.p_sigmask=" 6471.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6481.89Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 6491.89Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 6501.89Skamil 6511.89Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask))); 6521.89Skamil 6531.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 6541.88Skamil switch (sig) { 6551.88Skamil case SIGTRAP: 6561.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 6571.88Skamil break; 6581.88Skamil case SIGSEGV: 6591.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 6601.88Skamil break; 6611.88Skamil case SIGILL: 6621.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 6631.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 6641.88Skamil break; 6651.88Skamil case SIGFPE: 6661.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 6671.88Skamil break; 6681.88Skamil case SIGBUS: 6691.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 6701.88Skamil break; 6711.88Skamil } 6721.88Skamil 6731.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 6741.88Skamil 6751.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6761.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6771.88Skamil 6781.88Skamil validate_status_signaled(status, SIGKILL, 0); 6791.88Skamil 6801.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6811.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 6821.88Skamil} 6831.88Skamil 6841.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig) \ 6851.88SkamilATF_TC(test); \ 6861.88SkamilATF_TC_HEAD(test, tc) \ 6871.88Skamil{ \ 6881.88Skamil atf_tc_set_md_var(tc, "descr", \ 6891.88Skamil "Verify masked crash signal " #sig " in a child after " \ 6901.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 6911.88Skamil} \ 6921.88Skamil \ 6931.88SkamilATF_TC_BODY(test, tc) \ 6941.88Skamil{ \ 6951.88Skamil \ 6961.88Skamil traceme_signalmasked_crash(sig); \ 6971.88Skamil} 6981.88Skamil 6991.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP) 7001.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV) 7011.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL) 7021.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE) 7031.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS) 7041.88Skamil 7051.88Skamil/// ---------------------------------------------------------------------------- 7061.88Skamil 7071.88Skamilstatic void 7081.88Skamiltraceme_signalignored_crash(int sig) 7091.88Skamil{ 7101.90Skamil const int sigval = SIGSTOP; 7111.88Skamil pid_t child, wpid; 7121.88Skamil#if defined(TWAIT_HAVE_STATUS) 7131.88Skamil int status; 7141.88Skamil#endif 7151.88Skamil struct sigaction sa; 7161.88Skamil struct ptrace_siginfo info; 7171.90Skamil struct kinfo_proc2 kp; 7181.90Skamil size_t len = sizeof(kp); 7191.90Skamil 7201.90Skamil int name[6]; 7211.90Skamil const size_t namelen = __arraycount(name); 7221.90Skamil ki_sigset_t kp_sigignore; 7231.88Skamil 7241.88Skamil#ifndef PTRACE_ILLEGAL_ASM 7251.88Skamil if (sig == SIGILL) 7261.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 7271.88Skamil#endif 7281.88Skamil 7291.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 7301.114Skamil atf_tc_skip("FP exceptions are not supported"); 7311.114Skamil 7321.88Skamil memset(&info, 0, sizeof(info)); 7331.88Skamil 7341.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 7351.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 7361.88Skamil if (child == 0) { 7371.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 7381.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 7391.88Skamil 7401.88Skamil memset(&sa, 0, sizeof(sa)); 7411.88Skamil sa.sa_handler = SIG_IGN; 7421.88Skamil sigemptyset(&sa.sa_mask); 7431.88Skamil 7441.88Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 7451.88Skamil 7461.90Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 7471.90Skamil FORKEE_ASSERT(raise(sigval) == 0); 7481.90Skamil 7491.88Skamil DPRINTF("Before executing a trap\n"); 7501.88Skamil switch (sig) { 7511.88Skamil case SIGTRAP: 7521.88Skamil trigger_trap(); 7531.88Skamil break; 7541.88Skamil case SIGSEGV: 7551.88Skamil trigger_segv(); 7561.88Skamil break; 7571.88Skamil case SIGILL: 7581.88Skamil trigger_ill(); 7591.88Skamil break; 7601.88Skamil case SIGFPE: 7611.88Skamil trigger_fpe(); 7621.88Skamil break; 7631.88Skamil case SIGBUS: 7641.88Skamil trigger_bus(); 7651.88Skamil break; 7661.88Skamil default: 7671.88Skamil /* NOTREACHED */ 7681.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7691.88Skamil } 7701.88Skamil 7711.88Skamil /* NOTREACHED */ 7721.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7731.88Skamil } 7741.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 7751.88Skamil 7761.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7771.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 7781.88Skamil 7791.90Skamil validate_status_stopped(status, sigval); 7801.90Skamil 7811.90Skamil name[0] = CTL_KERN, 7821.90Skamil name[1] = KERN_PROC2, 7831.90Skamil name[2] = KERN_PROC_PID; 7841.90Skamil name[3] = child; 7851.90Skamil name[4] = sizeof(kp); 7861.90Skamil name[5] = 1; 7871.90Skamil 7881.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 7891.90Skamil 7901.90Skamil kp_sigignore = kp.p_sigignore; 7911.90Skamil 7921.90Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 7931.90Skamil SYSCALL_REQUIRE( 7941.90Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 7951.90Skamil 7961.90Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 7971.90Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 7981.90Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 7991.90Skamil info.psi_siginfo.si_errno); 8001.90Skamil 8011.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 8021.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 8031.90Skamil 8041.90Skamil DPRINTF("Before resuming the child process where it left off and " 8051.90Skamil "without signal to be sent\n"); 8061.90Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 8071.90Skamil 8081.90Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8091.90Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8101.90Skamil 8111.88Skamil validate_status_stopped(status, sig); 8121.88Skamil 8131.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 8141.88Skamil SYSCALL_REQUIRE( 8151.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8161.88Skamil 8171.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8181.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8191.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8201.88Skamil info.psi_siginfo.si_errno); 8211.88Skamil 8221.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8231.90Skamil 8241.90Skamil DPRINTF("kp_sigignore=" 8251.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8261.90Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 8271.90Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 8281.90Skamil 8291.90Skamil DPRINTF("kp.p_sigignore=" 8301.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8311.90Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 8321.90Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 8331.90Skamil 8341.90Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore))); 8351.90Skamil 8361.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 8371.88Skamil switch (sig) { 8381.88Skamil case SIGTRAP: 8391.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 8401.88Skamil break; 8411.88Skamil case SIGSEGV: 8421.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 8431.88Skamil break; 8441.88Skamil case SIGILL: 8451.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 8461.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 8471.88Skamil break; 8481.88Skamil case SIGFPE: 8491.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 8501.88Skamil break; 8511.88Skamil case SIGBUS: 8521.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 8531.88Skamil break; 8541.88Skamil } 8551.88Skamil 8561.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 8571.88Skamil 8581.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8591.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8601.88Skamil 8611.88Skamil validate_status_signaled(status, SIGKILL, 0); 8621.88Skamil 8631.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8641.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 8651.88Skamil} 8661.88Skamil 8671.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig) \ 8681.88SkamilATF_TC(test); \ 8691.88SkamilATF_TC_HEAD(test, tc) \ 8701.88Skamil{ \ 8711.88Skamil atf_tc_set_md_var(tc, "descr", \ 8721.88Skamil "Verify ignored crash signal " #sig " in a child after " \ 8731.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 8741.88Skamil} \ 8751.88Skamil \ 8761.88SkamilATF_TC_BODY(test, tc) \ 8771.88Skamil{ \ 8781.88Skamil \ 8791.88Skamil traceme_signalignored_crash(sig); \ 8801.88Skamil} 8811.88Skamil 8821.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP) 8831.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV) 8841.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL) 8851.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE) 8861.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS) 8871.88Skamil 8881.88Skamil/// ---------------------------------------------------------------------------- 8891.88Skamil 8901.88Skamilstatic void 8911.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught) 8921.1Skamil{ 8931.1Skamil const int exitval = 5; 8941.34Skamil const int sigval = SIGSTOP; 8951.1Skamil pid_t child, wpid; 8961.1Skamil struct sigaction sa; 8971.1Skamil#if defined(TWAIT_HAVE_STATUS) 8981.1Skamil int status; 8991.1Skamil#endif 9001.61Skre struct ptrace_siginfo info; 9011.1Skamil 9021.45Skamil memset(&info, 0, sizeof(info)); 9031.45Skamil 9041.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 9051.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 9061.1Skamil if (child == 0) { 9071.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 9081.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 9091.1Skamil 9101.34Skamil sa.sa_handler = sah; 9111.1Skamil sa.sa_flags = SA_SIGINFO; 9121.1Skamil sigemptyset(&sa.sa_mask); 9131.1Skamil 9141.1Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 9151.1Skamil 9161.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 9171.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 9181.1Skamil 9191.34Skamil FORKEE_ASSERT_EQ(*traceme_caught, 1); 9201.1Skamil 9211.13Schristos DPRINTF("Before exiting of the child process\n"); 9221.1Skamil _exit(exitval); 9231.1Skamil } 9241.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 9251.1Skamil 9261.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9271.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9281.1Skamil 9291.1Skamil validate_status_stopped(status, sigval); 9301.1Skamil 9311.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 9321.61Skre SYSCALL_REQUIRE( 9331.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 9341.45Skamil 9351.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 9361.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 9371.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 9381.45Skamil info.psi_siginfo.si_errno); 9391.45Skamil 9401.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 9411.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 9421.45Skamil 9431.13Schristos DPRINTF("Before resuming the child process where it left off and with " 9441.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 9451.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 9461.1Skamil 9471.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9481.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9491.1Skamil 9501.1Skamil validate_status_exited(status, exitval); 9511.1Skamil 9521.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 9531.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 9541.1Skamil} 9551.1Skamil 9561.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig) \ 9571.61SkreATF_TC(test); \ 9581.61SkreATF_TC_HEAD(test, tc) \ 9591.61Skre{ \ 9601.61Skre atf_tc_set_md_var(tc, "descr", \ 9611.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 9621.61Skre "handled correctly and caught by a signal handler"); \ 9631.61Skre} \ 9641.61Skre \ 9651.61Skrestatic int test##_caught = 0; \ 9661.61Skre \ 9671.61Skrestatic void \ 9681.61Skretest##_sighandler(int arg) \ 9691.61Skre{ \ 9701.61Skre FORKEE_ASSERT_EQ(arg, sig); \ 9711.61Skre \ 9721.61Skre ++ test##_caught; \ 9731.61Skre} \ 9741.61Skre \ 9751.61SkreATF_TC_BODY(test, tc) \ 9761.61Skre{ \ 9771.61Skre \ 9781.61Skre traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \ 9791.34Skamil} 9801.34Skamil 9811.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered. 9821.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */ 9831.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP) /* hangup */ 9841.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */ 9851.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */ 9861.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */ 9871.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */ 9881.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */ 9891.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */ 9901.34Skamil 9911.34Skamil/// ---------------------------------------------------------------------------- 9921.34Skamil 9931.35Skamilstatic void 9941.50Skamiltraceme_sendsignal_masked(int sigsent) 9951.50Skamil{ 9961.50Skamil const int exitval = 5; 9971.50Skamil const int sigval = SIGSTOP; 9981.50Skamil pid_t child, wpid; 9991.50Skamil sigset_t set; 10001.50Skamil#if defined(TWAIT_HAVE_STATUS) 10011.50Skamil int status; 10021.50Skamil#endif 10031.61Skre struct ptrace_siginfo info; 10041.50Skamil 10051.50Skamil memset(&info, 0, sizeof(info)); 10061.50Skamil 10071.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 10081.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 10091.50Skamil if (child == 0) { 10101.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 10111.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 10121.50Skamil 10131.50Skamil sigemptyset(&set); 10141.50Skamil sigaddset(&set, sigsent); 10151.50Skamil FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 10161.50Skamil 10171.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 10181.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 10191.50Skamil 10201.50Skamil _exit(exitval); 10211.50Skamil } 10221.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 10231.50Skamil 10241.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10251.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10261.50Skamil 10271.50Skamil validate_status_stopped(status, sigval); 10281.50Skamil 10291.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 10301.61Skre SYSCALL_REQUIRE( 10311.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 10321.50Skamil 10331.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 10341.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 10351.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 10361.50Skamil info.psi_siginfo.si_errno); 10371.50Skamil 10381.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 10391.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 10401.50Skamil 10411.50Skamil DPRINTF("Before resuming the child process where it left off and with " 10421.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 10431.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 10441.50Skamil 10451.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10461.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10471.50Skamil 10481.50Skamil validate_status_exited(status, exitval); 10491.50Skamil 10501.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 10511.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 10521.50Skamil} 10531.50Skamil 10541.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig) \ 10551.61SkreATF_TC(test); \ 10561.61SkreATF_TC_HEAD(test, tc) \ 10571.61Skre{ \ 10581.61Skre atf_tc_set_md_var(tc, "descr", \ 10591.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 10601.61Skre "handled correctly and the signal is masked by SIG_BLOCK"); \ 10611.61Skre} \ 10621.61Skre \ 10631.61SkreATF_TC_BODY(test, tc) \ 10641.61Skre{ \ 10651.61Skre \ 10661.61Skre traceme_sendsignal_masked(sig); \ 10671.50Skamil} 10681.50Skamil 10691.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 10701.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */ 10711.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP) /* hangup */ 10721.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */ 10731.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */ 10741.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */ 10751.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */ 10761.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */ 10771.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */ 10781.50Skamil 10791.50Skamil/// ---------------------------------------------------------------------------- 10801.50Skamil 10811.50Skamilstatic void 10821.50Skamiltraceme_sendsignal_ignored(int sigsent) 10831.50Skamil{ 10841.50Skamil const int exitval = 5; 10851.50Skamil const int sigval = SIGSTOP; 10861.50Skamil pid_t child, wpid; 10871.50Skamil struct sigaction sa; 10881.50Skamil#if defined(TWAIT_HAVE_STATUS) 10891.50Skamil int status; 10901.50Skamil#endif 10911.61Skre struct ptrace_siginfo info; 10921.50Skamil 10931.50Skamil memset(&info, 0, sizeof(info)); 10941.50Skamil 10951.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 10961.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 10971.50Skamil if (child == 0) { 10981.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 10991.61Skre 11001.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 11011.50Skamil 11021.50Skamil memset(&sa, 0, sizeof(sa)); 11031.50Skamil sa.sa_handler = SIG_IGN; 11041.50Skamil sigemptyset(&sa.sa_mask); 11051.50Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 11061.50Skamil 11071.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 11081.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 11091.50Skamil 11101.50Skamil _exit(exitval); 11111.50Skamil } 11121.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 11131.50Skamil 11141.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11151.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11161.50Skamil 11171.50Skamil validate_status_stopped(status, sigval); 11181.50Skamil 11191.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 11201.61Skre SYSCALL_REQUIRE( 11211.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 11221.50Skamil 11231.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 11241.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 11251.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 11261.50Skamil info.psi_siginfo.si_errno); 11271.50Skamil 11281.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 11291.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 11301.50Skamil 11311.50Skamil DPRINTF("Before resuming the child process where it left off and with " 11321.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 11331.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 11341.50Skamil 11351.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11361.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11371.50Skamil 11381.50Skamil validate_status_exited(status, exitval); 11391.50Skamil 11401.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 11411.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 11421.50Skamil} 11431.50Skamil 11441.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig) \ 11451.61SkreATF_TC(test); \ 11461.61SkreATF_TC_HEAD(test, tc) \ 11471.61Skre{ \ 11481.61Skre atf_tc_set_md_var(tc, "descr", \ 11491.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 11501.61Skre "handled correctly and the signal is masked by SIG_IGN"); \ 11511.61Skre} \ 11521.61Skre \ 11531.61SkreATF_TC_BODY(test, tc) \ 11541.61Skre{ \ 11551.61Skre \ 11561.61Skre traceme_sendsignal_ignored(sig); \ 11571.50Skamil} 11581.50Skamil 11591.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 11601.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */ 11611.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP) /* hangup */ 11621.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */ 11631.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */ 11641.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */ 11651.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */ 11661.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */ 11671.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */ 11681.50Skamil 11691.50Skamil/// ---------------------------------------------------------------------------- 11701.50Skamil 11711.50Skamilstatic void 11721.50Skamiltraceme_sendsignal_simple(int sigsent) 11731.1Skamil{ 11741.35Skamil const int sigval = SIGSTOP; 11751.35Skamil int exitval = 0; 11761.1Skamil pid_t child, wpid; 11771.1Skamil#if defined(TWAIT_HAVE_STATUS) 11781.1Skamil int status; 11791.85Skamil int expect_core; 11801.85Skamil 11811.85Skamil switch (sigsent) { 11821.85Skamil case SIGABRT: 11831.85Skamil case SIGTRAP: 11841.85Skamil case SIGBUS: 11851.85Skamil case SIGILL: 11861.85Skamil case SIGFPE: 11871.85Skamil case SIGSEGV: 11881.85Skamil expect_core = 1; 11891.85Skamil break; 11901.85Skamil default: 11911.85Skamil expect_core = 0; 11921.85Skamil break; 11931.85Skamil } 11941.1Skamil#endif 11951.61Skre struct ptrace_siginfo info; 11961.1Skamil 11971.45Skamil memset(&info, 0, sizeof(info)); 11981.45Skamil 11991.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 12001.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 12011.1Skamil if (child == 0) { 12021.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 12031.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 12041.1Skamil 12051.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 12061.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 12071.1Skamil 12081.35Skamil switch (sigsent) { 12091.35Skamil case SIGCONT: 12101.48Skamil case SIGSTOP: 12111.35Skamil _exit(exitval); 12121.35Skamil default: 12131.35Skamil /* NOTREACHED */ 12141.35Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 12151.35Skamil } 12161.1Skamil } 12171.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 12181.1Skamil 12191.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12201.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12211.1Skamil 12221.1Skamil validate_status_stopped(status, sigval); 12231.1Skamil 12241.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 12251.61Skre SYSCALL_REQUIRE( 12261.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 12271.45Skamil 12281.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12291.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 12301.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12311.45Skamil info.psi_siginfo.si_errno); 12321.45Skamil 12331.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12341.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12351.45Skamil 12361.13Schristos DPRINTF("Before resuming the child process where it left off and with " 12371.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 12381.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 12391.1Skamil 12401.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12411.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12421.1Skamil 12431.35Skamil switch (sigsent) { 12441.48Skamil case SIGSTOP: 12451.48Skamil validate_status_stopped(status, sigsent); 12461.48Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 12471.61Skre "child\n"); 12481.48Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 12491.61Skre sizeof(info)) != -1); 12501.48Skamil 12511.48Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12521.48Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 12531.61Skre "si_errno=%#x\n", 12541.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12551.61Skre info.psi_siginfo.si_errno); 12561.48Skamil 12571.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12581.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12591.48Skamil 12601.48Skamil DPRINTF("Before resuming the child process where it left off " 12611.61Skre "and with signal %s to be sent\n", strsignal(sigsent)); 12621.48Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 12631.48Skamil 12641.48Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12651.48Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 12661.61Skre child); 12671.48Skamil /* FALLTHROUGH */ 12681.35Skamil case SIGCONT: 12691.35Skamil validate_status_exited(status, exitval); 12701.35Skamil break; 12711.35Skamil default: 12721.35Skamil validate_status_signaled(status, sigsent, expect_core); 12731.35Skamil break; 12741.35Skamil } 12751.1Skamil 12761.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 12771.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 12781.1Skamil} 12791.1Skamil 12801.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig) \ 12811.61SkreATF_TC(test); \ 12821.61SkreATF_TC_HEAD(test, tc) \ 12831.61Skre{ \ 12841.61Skre atf_tc_set_md_var(tc, "descr", \ 12851.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 12861.61Skre "handled correctly in a child without a signal handler"); \ 12871.61Skre} \ 12881.61Skre \ 12891.61SkreATF_TC_BODY(test, tc) \ 12901.61Skre{ \ 12911.61Skre \ 12921.61Skre traceme_sendsignal_simple(sig); \ 12931.35Skamil} 12941.35Skamil 12951.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/ 12961.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/ 12971.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */ 12981.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP) /* hangup */ 12991.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */ 13001.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */ 13011.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */ 13021.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */ 13031.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */ 13041.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */ 13051.35Skamil 13061.35Skamil/// ---------------------------------------------------------------------------- 13071.35Skamil 13081.37SkamilATF_TC(traceme_pid1_parent); 13091.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc) 13101.37Skamil{ 13111.37Skamil atf_tc_set_md_var(tc, "descr", 13121.37Skamil "Verify that PT_TRACE_ME is not allowed when our parent is PID1"); 13131.37Skamil} 13141.37Skamil 13151.37SkamilATF_TC_BODY(traceme_pid1_parent, tc) 13161.37Skamil{ 13171.37Skamil struct msg_fds parent_child; 13181.37Skamil int exitval_child1 = 1, exitval_child2 = 2; 13191.37Skamil pid_t child1, child2, wpid; 13201.37Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 13211.37Skamil#if defined(TWAIT_HAVE_STATUS) 13221.37Skamil int status; 13231.37Skamil#endif 13241.37Skamil 13251.37Skamil SYSCALL_REQUIRE(msg_open(&parent_child) == 0); 13261.37Skamil 13271.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13281.37Skamil SYSCALL_REQUIRE((child1 = fork()) != -1); 13291.37Skamil if (child1 == 0) { 13301.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13311.37Skamil SYSCALL_REQUIRE((child2 = fork()) != -1); 13321.37Skamil if (child2 != 0) { 13331.37Skamil DPRINTF("Parent process PID=%d, child2's PID=%d\n", 13341.61Skre getpid(), child2); 13351.37Skamil _exit(exitval_child1); 13361.37Skamil } 13371.37Skamil CHILD_FROM_PARENT("exit child1", parent_child, msg); 13381.37Skamil 13391.37Skamil DPRINTF("Assert that our parent is PID1 (initproc)\n"); 13401.37Skamil FORKEE_ASSERT_EQ(getppid(), 1); 13411.37Skamil 13421.37Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 13431.37Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1); 13441.37Skamil SYSCALL_REQUIRE_ERRNO(errno, EPERM); 13451.37Skamil 13461.37Skamil CHILD_TO_PARENT("child2 exiting", parent_child, msg); 13471.37Skamil 13481.37Skamil _exit(exitval_child2); 13491.37Skamil } 13501.37Skamil DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1); 13511.37Skamil 13521.37Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 13531.61Skre TWAIT_REQUIRE_SUCCESS( 13541.61Skre wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1); 13551.37Skamil 13561.37Skamil validate_status_exited(status, exitval_child1); 13571.37Skamil 13581.37Skamil DPRINTF("Notify that child1 is dead\n"); 13591.37Skamil PARENT_TO_CHILD("exit child1", parent_child, msg); 13601.37Skamil 13611.37Skamil DPRINTF("Wait for exiting of child2\n"); 13621.37Skamil PARENT_FROM_CHILD("child2 exiting", parent_child, msg); 13631.37Skamil} 13641.37Skamil 13651.37Skamil/// ---------------------------------------------------------------------------- 13661.37Skamil 13671.40Skamilstatic void 13681.40Skamiltraceme_vfork_raise(int sigval) 13691.40Skamil{ 13701.46Skamil const int exitval = 5, exitval_watcher = 10; 13711.46Skamil pid_t child, parent, watcher, wpid; 13721.46Skamil int rv; 13731.40Skamil#if defined(TWAIT_HAVE_STATUS) 13741.40Skamil int status; 13751.85Skamil 13761.85Skamil /* volatile workarounds GCC -Werror=clobbered */ 13771.85Skamil volatile int expect_core; 13781.85Skamil 13791.85Skamil switch (sigval) { 13801.85Skamil case SIGABRT: 13811.85Skamil case SIGTRAP: 13821.85Skamil case SIGBUS: 13831.85Skamil case SIGILL: 13841.85Skamil case SIGFPE: 13851.85Skamil case SIGSEGV: 13861.85Skamil expect_core = 1; 13871.85Skamil break; 13881.85Skamil default: 13891.85Skamil expect_core = 0; 13901.85Skamil break; 13911.85Skamil } 13921.40Skamil#endif 13931.40Skamil 13941.46Skamil /* 13951.46Skamil * Spawn a dedicated thread to watch for a stopped child and emit 13961.46Skamil * the SIGKILL signal to it. 13971.46Skamil * 13981.46Skamil * vfork(2) might clobber watcher, this means that it's safer and 13991.46Skamil * simpler to reparent this process to initproc and forget about it. 14001.46Skamil */ 14011.46Skamil if (sigval == SIGSTOP) { 14021.46Skamil parent = getpid(); 14031.46Skamil 14041.46Skamil watcher = fork(); 14051.46Skamil ATF_REQUIRE(watcher != 1); 14061.46Skamil if (watcher == 0) { 14071.46Skamil /* Double fork(2) trick to reparent to initproc */ 14081.46Skamil watcher = fork(); 14091.46Skamil FORKEE_ASSERT_NEQ(watcher, -1); 14101.46Skamil if (watcher != 0) 14111.46Skamil _exit(exitval_watcher); 14121.46Skamil 14131.46Skamil child = await_stopped_child(parent); 14141.46Skamil 14151.46Skamil errno = 0; 14161.46Skamil rv = kill(child, SIGKILL); 14171.46Skamil FORKEE_ASSERT_EQ(rv, 0); 14181.46Skamil FORKEE_ASSERT_EQ(errno, 0); 14191.46Skamil 14201.46Skamil /* This exit value will be collected by initproc */ 14211.46Skamil _exit(0); 14221.46Skamil } 14231.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14241.46Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0), 14251.61Skre watcher); 14261.46Skamil 14271.46Skamil validate_status_exited(status, exitval_watcher); 14281.46Skamil 14291.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14301.61Skre TWAIT_REQUIRE_FAILURE(ECHILD, 14311.61Skre wpid = TWAIT_GENERIC(watcher, &status, 0)); 14321.46Skamil } 14331.46Skamil 14341.40Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 14351.40Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 14361.40Skamil if (child == 0) { 14371.40Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 14381.40Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 14391.40Skamil 14401.40Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 14411.40Skamil FORKEE_ASSERT(raise(sigval) == 0); 14421.40Skamil 14431.40Skamil switch (sigval) { 14441.46Skamil case SIGSTOP: 14451.40Skamil case SIGKILL: 14461.40Skamil case SIGABRT: 14471.40Skamil case SIGHUP: 14481.85Skamil case SIGTRAP: 14491.85Skamil case SIGBUS: 14501.85Skamil case SIGILL: 14511.85Skamil case SIGFPE: 14521.85Skamil case SIGSEGV: 14531.40Skamil /* NOTREACHED */ 14541.40Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 14551.70Smrg __unreachable(); 14561.40Skamil default: 14571.40Skamil DPRINTF("Before exiting of the child process\n"); 14581.40Skamil _exit(exitval); 14591.40Skamil } 14601.40Skamil } 14611.40Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 14621.40Skamil 14631.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14641.40Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 14651.40Skamil 14661.40Skamil switch (sigval) { 14671.40Skamil case SIGKILL: 14681.40Skamil case SIGABRT: 14691.40Skamil case SIGHUP: 14701.85Skamil case SIGTRAP: 14711.85Skamil case SIGBUS: 14721.85Skamil case SIGILL: 14731.85Skamil case SIGFPE: 14741.85Skamil case SIGSEGV: 14751.40Skamil validate_status_signaled(status, sigval, expect_core); 14761.40Skamil break; 14771.40Skamil case SIGSTOP: 14781.46Skamil validate_status_signaled(status, SIGKILL, 0); 14791.46Skamil break; 14801.40Skamil case SIGCONT: 14811.47Skamil case SIGTSTP: 14821.47Skamil case SIGTTIN: 14831.47Skamil case SIGTTOU: 14841.40Skamil validate_status_exited(status, exitval); 14851.40Skamil break; 14861.40Skamil default: 14871.40Skamil /* NOTREACHED */ 14881.40Skamil ATF_REQUIRE(0 && "NOT IMPLEMENTED"); 14891.40Skamil break; 14901.40Skamil } 14911.40Skamil 14921.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14931.40Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 14941.40Skamil} 14951.40Skamil 14961.61Skre#define TRACEME_VFORK_RAISE(test, sig) \ 14971.61SkreATF_TC(test); \ 14981.61SkreATF_TC_HEAD(test, tc) \ 14991.61Skre{ \ 15001.61Skre atf_tc_set_md_var(tc, "descr", \ 15011.61Skre "Verify PT_TRACE_ME followed by raise of " #sig " in a " \ 15021.61Skre "vfork(2)ed child"); \ 15031.61Skre} \ 15041.61Skre \ 15051.61SkreATF_TC_BODY(test, tc) \ 15061.61Skre{ \ 15071.61Skre \ 15081.61Skre traceme_vfork_raise(sig); \ 15091.40Skamil} 15101.40Skamil 15111.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */ 15121.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */ 15131.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */ 15141.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */ 15151.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */ 15161.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */ 15171.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP) /* hangup */ 15181.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */ 15191.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */ 15201.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */ 15211.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */ 15221.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */ 15231.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */ 15241.40Skamil 15251.40Skamil/// ---------------------------------------------------------------------------- 15261.40Skamil 15271.52Skamilstatic void 15281.52Skamiltraceme_vfork_crash(int sig) 15291.41Skamil{ 15301.41Skamil pid_t child, wpid; 15311.41Skamil#if defined(TWAIT_HAVE_STATUS) 15321.41Skamil int status; 15331.41Skamil#endif 15341.41Skamil 15351.71Skamil#ifndef PTRACE_ILLEGAL_ASM 15361.71Skamil if (sig == SIGILL) 15371.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 15381.71Skamil#endif 15391.71Skamil 15401.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 15411.114Skamil atf_tc_skip("FP exceptions are not supported"); 15421.114Skamil 15431.41Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 15441.41Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 15451.41Skamil if (child == 0) { 15461.41Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 15471.41Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 15481.41Skamil 15491.52Skamil DPRINTF("Before executing a trap\n"); 15501.52Skamil switch (sig) { 15511.52Skamil case SIGTRAP: 15521.52Skamil trigger_trap(); 15531.52Skamil break; 15541.52Skamil case SIGSEGV: 15551.52Skamil trigger_segv(); 15561.52Skamil break; 15571.52Skamil case SIGILL: 15581.52Skamil trigger_ill(); 15591.52Skamil break; 15601.52Skamil case SIGFPE: 15611.52Skamil trigger_fpe(); 15621.52Skamil break; 15631.52Skamil case SIGBUS: 15641.52Skamil trigger_bus(); 15651.52Skamil break; 15661.52Skamil default: 15671.52Skamil /* NOTREACHED */ 15681.52Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15691.52Skamil } 15701.41Skamil 15711.41Skamil /* NOTREACHED */ 15721.41Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15731.41Skamil } 15741.41Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 15751.41Skamil 15761.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15771.41Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 15781.41Skamil 15791.52Skamil validate_status_signaled(status, sig, 1); 15801.41Skamil 15811.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15821.41Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15831.41Skamil} 15841.41Skamil 15851.61Skre#define TRACEME_VFORK_CRASH(test, sig) \ 15861.61SkreATF_TC(test); \ 15871.61SkreATF_TC_HEAD(test, tc) \ 15881.61Skre{ \ 15891.61Skre atf_tc_set_md_var(tc, "descr", \ 15901.61Skre "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 15911.61Skre "vfork(2)ed child"); \ 15921.61Skre} \ 15931.61Skre \ 15941.61SkreATF_TC_BODY(test, tc) \ 15951.61Skre{ \ 15961.61Skre \ 15971.61Skre traceme_vfork_crash(sig); \ 15981.52Skamil} 15991.52Skamil 16001.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP) 16011.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV) 16021.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL) 16031.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE) 16041.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS) 16051.52Skamil 16061.41Skamil/// ---------------------------------------------------------------------------- 16071.41Skamil 16081.92Skamilstatic void 16091.92Skamiltraceme_vfork_signalmasked_crash(int sig) 16101.92Skamil{ 16111.92Skamil pid_t child, wpid; 16121.92Skamil#if defined(TWAIT_HAVE_STATUS) 16131.92Skamil int status; 16141.92Skamil#endif 16151.92Skamil sigset_t intmask; 16161.92Skamil 16171.92Skamil#ifndef PTRACE_ILLEGAL_ASM 16181.92Skamil if (sig == SIGILL) 16191.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 16201.92Skamil#endif 16211.92Skamil 16221.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 16231.114Skamil atf_tc_skip("FP exceptions are not supported"); 16241.114Skamil 16251.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 16261.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 16271.92Skamil if (child == 0) { 16281.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 16291.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 16301.92Skamil 16311.92Skamil sigemptyset(&intmask); 16321.92Skamil sigaddset(&intmask, sig); 16331.92Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 16341.92Skamil 16351.92Skamil DPRINTF("Before executing a trap\n"); 16361.92Skamil switch (sig) { 16371.92Skamil case SIGTRAP: 16381.92Skamil trigger_trap(); 16391.92Skamil break; 16401.92Skamil case SIGSEGV: 16411.92Skamil trigger_segv(); 16421.92Skamil break; 16431.92Skamil case SIGILL: 16441.92Skamil trigger_ill(); 16451.92Skamil break; 16461.92Skamil case SIGFPE: 16471.92Skamil trigger_fpe(); 16481.92Skamil break; 16491.92Skamil case SIGBUS: 16501.92Skamil trigger_bus(); 16511.92Skamil break; 16521.92Skamil default: 16531.92Skamil /* NOTREACHED */ 16541.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16551.92Skamil } 16561.92Skamil 16571.92Skamil /* NOTREACHED */ 16581.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16591.92Skamil } 16601.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 16611.92Skamil 16621.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16631.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 16641.92Skamil 16651.92Skamil validate_status_signaled(status, sig, 1); 16661.92Skamil 16671.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16681.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 16691.92Skamil} 16701.92Skamil 16711.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig) \ 16721.92SkamilATF_TC(test); \ 16731.92SkamilATF_TC_HEAD(test, tc) \ 16741.92Skamil{ \ 16751.92Skamil atf_tc_set_md_var(tc, "descr", \ 16761.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16771.92Skamil "vfork(2)ed child with a masked signal"); \ 16781.92Skamil} \ 16791.92Skamil \ 16801.92SkamilATF_TC_BODY(test, tc) \ 16811.92Skamil{ \ 16821.92Skamil \ 16831.92Skamil traceme_vfork_signalmasked_crash(sig); \ 16841.92Skamil} 16851.92Skamil 16861.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP) 16871.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV) 16881.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL) 16891.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE) 16901.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS) 16911.92Skamil 16921.92Skamil/// ---------------------------------------------------------------------------- 16931.92Skamil 16941.92Skamilstatic void 16951.92Skamiltraceme_vfork_signalignored_crash(int sig) 16961.92Skamil{ 16971.92Skamil pid_t child, wpid; 16981.92Skamil#if defined(TWAIT_HAVE_STATUS) 16991.92Skamil int status; 17001.92Skamil#endif 17011.92Skamil struct sigaction sa; 17021.92Skamil 17031.92Skamil#ifndef PTRACE_ILLEGAL_ASM 17041.92Skamil if (sig == SIGILL) 17051.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 17061.92Skamil#endif 17071.92Skamil 17081.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 17091.114Skamil atf_tc_skip("FP exceptions are not supported"); 17101.114Skamil 17111.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 17121.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 17131.92Skamil if (child == 0) { 17141.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 17151.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 17161.92Skamil 17171.92Skamil memset(&sa, 0, sizeof(sa)); 17181.92Skamil sa.sa_handler = SIG_IGN; 17191.92Skamil sigemptyset(&sa.sa_mask); 17201.92Skamil 17211.92Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 17221.92Skamil 17231.92Skamil DPRINTF("Before executing a trap\n"); 17241.92Skamil switch (sig) { 17251.92Skamil case SIGTRAP: 17261.92Skamil trigger_trap(); 17271.92Skamil break; 17281.92Skamil case SIGSEGV: 17291.92Skamil trigger_segv(); 17301.92Skamil break; 17311.92Skamil case SIGILL: 17321.92Skamil trigger_ill(); 17331.92Skamil break; 17341.92Skamil case SIGFPE: 17351.92Skamil trigger_fpe(); 17361.92Skamil break; 17371.92Skamil case SIGBUS: 17381.92Skamil trigger_bus(); 17391.92Skamil break; 17401.92Skamil default: 17411.92Skamil /* NOTREACHED */ 17421.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17431.92Skamil } 17441.92Skamil 17451.92Skamil /* NOTREACHED */ 17461.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17471.92Skamil } 17481.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 17491.92Skamil 17501.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17511.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17521.92Skamil 17531.92Skamil validate_status_signaled(status, sig, 1); 17541.92Skamil 17551.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17561.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 17571.92Skamil} 17581.92Skamil 17591.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig) \ 17601.92SkamilATF_TC(test); \ 17611.92SkamilATF_TC_HEAD(test, tc) \ 17621.92Skamil{ \ 17631.92Skamil atf_tc_set_md_var(tc, "descr", \ 17641.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 17651.92Skamil "vfork(2)ed child with ignored signal"); \ 17661.92Skamil} \ 17671.92Skamil \ 17681.92SkamilATF_TC_BODY(test, tc) \ 17691.92Skamil{ \ 17701.92Skamil \ 17711.92Skamil traceme_vfork_signalignored_crash(sig); \ 17721.92Skamil} 17731.92Skamil 17741.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap, 17751.92Skamil SIGTRAP) 17761.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv, 17771.92Skamil SIGSEGV) 17781.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill, 17791.92Skamil SIGILL) 17801.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe, 17811.92Skamil SIGFPE) 17821.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus, 17831.92Skamil SIGBUS) 17841.92Skamil 17851.92Skamil/// ---------------------------------------------------------------------------- 17861.92Skamil 17871.96Skamilstatic void 17881.96Skamiltraceme_vfork_exec(bool masked, bool ignored) 17891.43Skamil{ 17901.43Skamil const int sigval = SIGTRAP; 17911.43Skamil pid_t child, wpid; 17921.43Skamil#if defined(TWAIT_HAVE_STATUS) 17931.43Skamil int status; 17941.43Skamil#endif 17951.96Skamil struct sigaction sa; 17961.61Skre struct ptrace_siginfo info; 17971.96Skamil sigset_t intmask; 17981.96Skamil struct kinfo_proc2 kp; 17991.96Skamil size_t len = sizeof(kp); 18001.96Skamil 18011.96Skamil int name[6]; 18021.96Skamil const size_t namelen = __arraycount(name); 18031.96Skamil ki_sigset_t kp_sigmask; 18041.96Skamil ki_sigset_t kp_sigignore; 18051.43Skamil 18061.43Skamil memset(&info, 0, sizeof(info)); 18071.43Skamil 18081.43Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 18091.43Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 18101.43Skamil if (child == 0) { 18111.43Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 18121.43Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 18131.43Skamil 18141.96Skamil if (masked) { 18151.96Skamil sigemptyset(&intmask); 18161.96Skamil sigaddset(&intmask, sigval); 18171.96Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 18181.96Skamil } 18191.96Skamil 18201.96Skamil if (ignored) { 18211.96Skamil memset(&sa, 0, sizeof(sa)); 18221.96Skamil sa.sa_handler = SIG_IGN; 18231.96Skamil sigemptyset(&sa.sa_mask); 18241.96Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 18251.96Skamil } 18261.96Skamil 18271.43Skamil DPRINTF("Before calling execve(2) from child\n"); 18281.43Skamil execlp("/bin/echo", "/bin/echo", NULL); 18291.43Skamil 18301.43Skamil /* NOTREACHED */ 18311.43Skamil FORKEE_ASSERTX(0 && "Not reached"); 18321.43Skamil } 18331.43Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 18341.43Skamil 18351.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 18361.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 18371.43Skamil 18381.43Skamil validate_status_stopped(status, sigval); 18391.43Skamil 18401.96Skamil name[0] = CTL_KERN, 18411.96Skamil name[1] = KERN_PROC2, 18421.96Skamil name[2] = KERN_PROC_PID; 18431.96Skamil name[3] = getpid(); 18441.96Skamil name[4] = sizeof(kp); 18451.96Skamil name[5] = 1; 18461.96Skamil 18471.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18481.96Skamil 18491.96Skamil if (masked) 18501.96Skamil kp_sigmask = kp.p_sigmask; 18511.96Skamil 18521.96Skamil if (ignored) 18531.96Skamil kp_sigignore = kp.p_sigignore; 18541.96Skamil 18551.96Skamil name[3] = getpid(); 18561.96Skamil 18571.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18581.96Skamil 18591.96Skamil if (masked) { 18601.96Skamil DPRINTF("kp_sigmask=" 18611.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18621.96Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 18631.96Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 18641.96Skamil 18651.96Skamil DPRINTF("kp.p_sigmask=" 18661.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18671.96Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 18681.96Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 18691.96Skamil 18701.96Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 18711.96Skamil sizeof(kp_sigmask))); 18721.96Skamil } 18731.96Skamil 18741.96Skamil if (ignored) { 18751.96Skamil DPRINTF("kp_sigignore=" 18761.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18771.96Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 18781.96Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 18791.96Skamil 18801.96Skamil DPRINTF("kp.p_sigignore=" 18811.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18821.96Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 18831.96Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 18841.96Skamil 18851.96Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 18861.96Skamil sizeof(kp_sigignore))); 18871.96Skamil } 18881.96Skamil 18891.43Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 18901.61Skre SYSCALL_REQUIRE( 18911.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 18921.43Skamil 18931.43Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 18941.43Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 18951.43Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 18961.43Skamil info.psi_siginfo.si_errno); 18971.43Skamil 18981.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 18991.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 19001.43Skamil 19011.43Skamil DPRINTF("Before resuming the child process where it left off and " 19021.43Skamil "without signal to be sent\n"); 19031.43Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 19041.43Skamil 19051.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19061.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 19071.43Skamil 19081.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19091.43Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 19101.43Skamil} 19111.43Skamil 19121.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored) \ 19131.96SkamilATF_TC(test); \ 19141.96SkamilATF_TC_HEAD(test, tc) \ 19151.96Skamil{ \ 19161.96Skamil atf_tc_set_md_var(tc, "descr", \ 19171.96Skamil "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed " \ 19181.96Skamil "child%s%s", masked ? " with masked signal" : "", \ 19191.96Skamil masked ? " with ignored signal" : ""); \ 19201.96Skamil} \ 19211.96Skamil \ 19221.96SkamilATF_TC_BODY(test, tc) \ 19231.96Skamil{ \ 19241.96Skamil \ 19251.96Skamil traceme_vfork_exec(masked, ignored); \ 19261.96Skamil} 19271.96Skamil 19281.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false) 19291.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false) 19301.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true) 19311.96Skamil 19321.43Skamil/// ---------------------------------------------------------------------------- 19331.43Skamil 19341.1Skamil#if defined(TWAIT_HAVE_PID) 19351.51Skamilstatic void 19361.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored) 19371.59Skamil{ 19381.94Skamil const int sigval = SIGSTOP; 19391.59Skamil struct msg_fds parent_tracee, parent_tracer; 19401.59Skamil const int exitval = 10; 19411.59Skamil pid_t tracee, tracer, wpid; 19421.59Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 19431.59Skamil#if defined(TWAIT_HAVE_STATUS) 19441.59Skamil int status; 19451.59Skamil#endif 19461.94Skamil struct sigaction sa; 19471.59Skamil struct ptrace_siginfo info; 19481.94Skamil sigset_t intmask; 19491.94Skamil struct kinfo_proc2 kp; 19501.94Skamil size_t len = sizeof(kp); 19511.94Skamil 19521.94Skamil int name[6]; 19531.94Skamil const size_t namelen = __arraycount(name); 19541.94Skamil ki_sigset_t kp_sigmask; 19551.94Skamil ki_sigset_t kp_sigignore; 19561.61Skre 19571.71Skamil#ifndef PTRACE_ILLEGAL_ASM 19581.71Skamil if (sig == SIGILL) 19591.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 19601.71Skamil#endif 19611.71Skamil 19621.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 19631.114Skamil atf_tc_skip("FP exceptions are not supported"); 19641.114Skamil 19651.59Skamil memset(&info, 0, sizeof(info)); 19661.59Skamil 19671.59Skamil DPRINTF("Spawn tracee\n"); 19681.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 19691.59Skamil tracee = atf_utils_fork(); 19701.59Skamil if (tracee == 0) { 19711.59Skamil // Wait for parent to let us crash 19721.59Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 19731.61Skre 19741.94Skamil if (masked) { 19751.94Skamil sigemptyset(&intmask); 19761.94Skamil sigaddset(&intmask, sig); 19771.94Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 19781.94Skamil } 19791.94Skamil 19801.94Skamil if (ignored) { 19811.94Skamil memset(&sa, 0, sizeof(sa)); 19821.94Skamil sa.sa_handler = SIG_IGN; 19831.94Skamil sigemptyset(&sa.sa_mask); 19841.94Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 19851.94Skamil } 19861.94Skamil 19871.94Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 19881.94Skamil FORKEE_ASSERT(raise(sigval) == 0); 19891.94Skamil 19901.59Skamil DPRINTF("Before executing a trap\n"); 19911.59Skamil switch (sig) { 19921.59Skamil case SIGTRAP: 19931.59Skamil trigger_trap(); 19941.59Skamil break; 19951.59Skamil case SIGSEGV: 19961.59Skamil trigger_segv(); 19971.59Skamil break; 19981.59Skamil case SIGILL: 19991.59Skamil trigger_ill(); 20001.59Skamil break; 20011.59Skamil case SIGFPE: 20021.59Skamil trigger_fpe(); 20031.59Skamil break; 20041.59Skamil case SIGBUS: 20051.59Skamil trigger_bus(); 20061.59Skamil break; 20071.59Skamil default: 20081.59Skamil /* NOTREACHED */ 20091.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20101.59Skamil } 20111.59Skamil 20121.59Skamil /* NOTREACHED */ 20131.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20141.59Skamil } 20151.59Skamil 20161.59Skamil DPRINTF("Spawn debugger\n"); 20171.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 20181.59Skamil tracer = atf_utils_fork(); 20191.59Skamil if (tracer == 0) { 20201.59Skamil /* Fork again and drop parent to reattach to PID 1 */ 20211.59Skamil tracer = atf_utils_fork(); 20221.59Skamil if (tracer != 0) 20231.61Skre _exit(exitval); 20241.59Skamil 20251.59Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 20261.59Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 20271.59Skamil 20281.59Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 20291.59Skamil FORKEE_REQUIRE_SUCCESS( 20301.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20311.59Skamil 20321.59Skamil forkee_status_stopped(status, SIGSTOP); 20331.59Skamil 20341.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20351.94Skamil "traced process\n"); 20361.94Skamil SYSCALL_REQUIRE( 20371.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20381.94Skamil 20391.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20401.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20411.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20421.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20431.94Skamil 20441.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 20451.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 20461.94Skamil 20471.59Skamil /* Resume tracee with PT_CONTINUE */ 20481.59Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 20491.59Skamil 20501.59Skamil /* Inform parent that tracer has attached to tracee */ 20511.59Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 20521.59Skamil 20531.59Skamil /* Wait for parent to tell use that tracee should have exited */ 20541.59Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 20551.59Skamil 20561.59Skamil /* Wait for tracee and assert that it exited */ 20571.59Skamil FORKEE_REQUIRE_SUCCESS( 20581.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20591.59Skamil 20601.94Skamil forkee_status_stopped(status, sigval); 20611.94Skamil 20621.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20631.94Skamil "traced process\n"); 20641.94Skamil SYSCALL_REQUIRE( 20651.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20661.94Skamil 20671.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20681.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20691.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20701.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20711.94Skamil 20721.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 20731.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 20741.94Skamil 20751.94Skamil name[0] = CTL_KERN, 20761.94Skamil name[1] = KERN_PROC2, 20771.94Skamil name[2] = KERN_PROC_PID; 20781.94Skamil name[3] = tracee; 20791.94Skamil name[4] = sizeof(kp); 20801.94Skamil name[5] = 1; 20811.94Skamil 20821.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 20831.94Skamil 20841.94Skamil if (masked) 20851.94Skamil kp_sigmask = kp.p_sigmask; 20861.94Skamil 20871.94Skamil if (ignored) 20881.94Skamil kp_sigignore = kp.p_sigignore; 20891.94Skamil 20901.94Skamil /* Resume tracee with PT_CONTINUE */ 20911.94Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 20921.94Skamil 20931.94Skamil /* Wait for tracee and assert that it exited */ 20941.94Skamil FORKEE_REQUIRE_SUCCESS( 20951.94Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20961.94Skamil 20971.93Skamil forkee_status_stopped(status, sig); 20981.59Skamil 20991.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 21001.61Skre "traced process\n"); 21011.61Skre SYSCALL_REQUIRE( 21021.61Skre ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 21031.59Skamil 21041.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21051.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21061.61Skre "si_errno=%#x\n", info.psi_siginfo.si_signo, 21071.61Skre info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 21081.59Skamil 21091.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig); 21101.94Skamil 21111.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21121.94Skamil 21131.94Skamil if (masked) { 21141.94Skamil DPRINTF("kp_sigmask=" 21151.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21161.94Skamil PRIx32 "\n", 21171.94Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 21181.94Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 21191.94Skamil 21201.94Skamil DPRINTF("kp.p_sigmask=" 21211.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21221.94Skamil PRIx32 "\n", 21231.94Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 21241.94Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 21251.94Skamil 21261.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask, 21271.94Skamil sizeof(kp_sigmask))); 21281.94Skamil } 21291.94Skamil 21301.94Skamil if (ignored) { 21311.94Skamil DPRINTF("kp_sigignore=" 21321.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21331.94Skamil PRIx32 "\n", 21341.94Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 21351.94Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 21361.94Skamil 21371.94Skamil DPRINTF("kp.p_sigignore=" 21381.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21391.94Skamil PRIx32 "\n", 21401.94Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 21411.94Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 21421.94Skamil 21431.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore, 21441.94Skamil sizeof(kp_sigignore))); 21451.94Skamil } 21461.94Skamil 21471.59Skamil switch (sig) { 21481.59Skamil case SIGTRAP: 21491.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 21501.59Skamil break; 21511.59Skamil case SIGSEGV: 21521.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 21531.59Skamil break; 21541.71Skamil case SIGILL: 21551.113Skamil FORKEE_ASSERT(info.psi_siginfo.si_code >= ILL_ILLOPC && 21561.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 21571.71Skamil break; 21581.59Skamil case SIGFPE: 21591.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 21601.59Skamil break; 21611.59Skamil case SIGBUS: 21621.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 21631.59Skamil break; 21641.59Skamil } 21651.59Skamil 21661.59Skamil FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1); 21671.59Skamil DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME); 21681.93Skamil FORKEE_REQUIRE_SUCCESS( 21691.61Skre wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21701.59Skamil 21711.93Skamil forkee_status_signaled(status, SIGKILL, 0); 21721.59Skamil 21731.71Skamil /* Inform parent that tracer is exiting normally */ 21741.71Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 21751.71Skamil 21761.59Skamil DPRINTF("Before exiting of the tracer process\n"); 21771.59Skamil _exit(0 /* collect by initproc */); 21781.59Skamil } 21791.59Skamil 21801.59Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 21811.59Skamil "calling %s()\n", TWAIT_FNAME); 21821.59Skamil TWAIT_REQUIRE_SUCCESS( 21831.59Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 21841.59Skamil 21851.59Skamil validate_status_exited(status, exitval); 21861.59Skamil 21871.59Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 21881.59Skamil TWAIT_FNAME); 21891.59Skamil TWAIT_REQUIRE_SUCCESS( 21901.59Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 21911.59Skamil 21921.59Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 21931.59Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 21941.59Skamil 21951.59Skamil DPRINTF("Resume the tracee and let it crash\n"); 21961.59Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 21971.59Skamil 21981.59Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 21991.59Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 22001.59Skamil 22011.59Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 22021.59Skamil TWAIT_FNAME); 22031.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22041.59Skamil 22051.59Skamil validate_status_signaled(status, SIGKILL, 0); 22061.59Skamil 22071.71Skamil DPRINTF("Await normal exit of tracer\n"); 22081.71Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 22091.71Skamil 22101.59Skamil msg_close(&parent_tracer); 22111.59Skamil msg_close(&parent_tracee); 22121.59Skamil} 22131.59Skamil 22141.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig) \ 22151.61SkreATF_TC(test); \ 22161.61SkreATF_TC_HEAD(test, tc) \ 22171.61Skre{ \ 22181.61Skre atf_tc_set_md_var(tc, "descr", \ 22191.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22201.94Skamil "the debuggee"); \ 22211.61Skre} \ 22221.61Skre \ 22231.61SkreATF_TC_BODY(test, tc) \ 22241.61Skre{ \ 22251.61Skre \ 22261.94Skamil unrelated_tracer_sees_crash(sig, false, false); \ 22271.59Skamil} 22281.59Skamil 22291.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP) 22301.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV) 22311.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL) 22321.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE) 22331.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS) 22341.94Skamil 22351.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig) \ 22361.94SkamilATF_TC(test); \ 22371.94SkamilATF_TC_HEAD(test, tc) \ 22381.94Skamil{ \ 22391.94Skamil atf_tc_set_md_var(tc, "descr", \ 22401.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22411.94Skamil "the debuggee with masked signal"); \ 22421.94Skamil} \ 22431.94Skamil \ 22441.94SkamilATF_TC_BODY(test, tc) \ 22451.94Skamil{ \ 22461.94Skamil \ 22471.94Skamil unrelated_tracer_sees_crash(sig, true, false); \ 22481.94Skamil} 22491.94Skamil 22501.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22511.94Skamil unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP) 22521.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22531.94Skamil unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV) 22541.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22551.94Skamil unrelated_tracer_sees_signalmasked_crash_ill, SIGILL) 22561.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22571.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE) 22581.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22591.94Skamil unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS) 22601.94Skamil 22611.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig) \ 22621.94SkamilATF_TC(test); \ 22631.94SkamilATF_TC_HEAD(test, tc) \ 22641.94Skamil{ \ 22651.94Skamil atf_tc_set_md_var(tc, "descr", \ 22661.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22671.94Skamil "the debuggee with signal ignored"); \ 22681.94Skamil} \ 22691.94Skamil \ 22701.94SkamilATF_TC_BODY(test, tc) \ 22711.94Skamil{ \ 22721.94Skamil \ 22731.94Skamil unrelated_tracer_sees_crash(sig, false, true); \ 22741.94Skamil} 22751.94Skamil 22761.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22771.94Skamil unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP) 22781.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22791.94Skamil unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV) 22801.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22811.94Skamil unrelated_tracer_sees_signalignored_crash_ill, SIGILL) 22821.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22831.94Skamil unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE) 22841.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22851.94Skamil unrelated_tracer_sees_signalignored_crash_bus, SIGBUS) 22861.59Skamil#endif 22871.59Skamil 22881.59Skamil/// ---------------------------------------------------------------------------- 22891.59Skamil 22901.59Skamil#if defined(TWAIT_HAVE_PID) 22911.59Skamilstatic void 22921.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated, 22931.67Skamil bool stopped) 22941.1Skamil{ 22951.51Skamil /* 22961.51Skamil * notimeout - disable timeout in await zombie function 22971.51Skamil * unrelated - attach from unrelated tracer reparented to initproc 22981.67Skamil * stopped - attach to a stopped process 22991.51Skamil */ 23001.1Skamil 23011.1Skamil struct msg_fds parent_tracee, parent_tracer; 23021.1Skamil const int exitval_tracee = 5; 23031.1Skamil const int exitval_tracer = 10; 23041.1Skamil pid_t tracee, tracer, wpid; 23051.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 23061.1Skamil#if defined(TWAIT_HAVE_STATUS) 23071.1Skamil int status; 23081.1Skamil#endif 23091.1Skamil 23101.67Skamil /* 23111.67Skamil * Only a subset of options are supported. 23121.67Skamil */ 23131.67Skamil ATF_REQUIRE((!notimeout && !unrelated && !stopped) || 23141.67Skamil (!notimeout && unrelated && !stopped) || 23151.67Skamil (notimeout && !unrelated && !stopped) || 23161.67Skamil (!notimeout && unrelated && stopped)); 23171.67Skamil 23181.13Schristos DPRINTF("Spawn tracee\n"); 23191.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 23201.1Skamil tracee = atf_utils_fork(); 23211.1Skamil if (tracee == 0) { 23221.67Skamil if (stopped) { 23231.67Skamil DPRINTF("Stop self PID %d\n", getpid()); 23241.67Skamil raise(SIGSTOP); 23251.67Skamil } 23261.67Skamil 23271.1Skamil // Wait for parent to let us exit 23281.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 23291.1Skamil _exit(exitval_tracee); 23301.1Skamil } 23311.1Skamil 23321.13Schristos DPRINTF("Spawn debugger\n"); 23331.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 23341.1Skamil tracer = atf_utils_fork(); 23351.1Skamil if (tracer == 0) { 23361.51Skamil if(unrelated) { 23371.51Skamil /* Fork again and drop parent to reattach to PID 1 */ 23381.51Skamil tracer = atf_utils_fork(); 23391.51Skamil if (tracer != 0) 23401.51Skamil _exit(exitval_tracer); 23411.51Skamil } 23421.51Skamil 23431.67Skamil if (stopped) { 23441.67Skamil DPRINTF("Await for a stopped parent PID %d\n", tracee); 23451.67Skamil await_stopped(tracee); 23461.67Skamil } 23471.67Skamil 23481.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 23491.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 23501.1Skamil 23511.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 23521.1Skamil FORKEE_REQUIRE_SUCCESS( 23531.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23541.1Skamil 23551.1Skamil forkee_status_stopped(status, SIGSTOP); 23561.1Skamil 23571.1Skamil /* Resume tracee with PT_CONTINUE */ 23581.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 23591.1Skamil 23601.1Skamil /* Inform parent that tracer has attached to tracee */ 23611.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 23621.1Skamil 23631.1Skamil /* Wait for parent to tell use that tracee should have exited */ 23641.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 23651.1Skamil 23661.1Skamil /* Wait for tracee and assert that it exited */ 23671.1Skamil FORKEE_REQUIRE_SUCCESS( 23681.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23691.1Skamil 23701.1Skamil forkee_status_exited(status, exitval_tracee); 23711.13Schristos DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee); 23721.1Skamil 23731.13Schristos DPRINTF("Before exiting of the tracer process\n"); 23741.51Skamil _exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer); 23751.51Skamil } 23761.51Skamil 23771.51Skamil if (unrelated) { 23781.51Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 23791.51Skamil "calling %s()\n", TWAIT_FNAME); 23801.51Skamil TWAIT_REQUIRE_SUCCESS( 23811.51Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 23821.51Skamil 23831.51Skamil validate_status_exited(status, exitval_tracer); 23841.51Skamil 23851.51Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 23861.51Skamil TWAIT_FNAME); 23871.51Skamil TWAIT_REQUIRE_SUCCESS( 23881.51Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 23891.1Skamil } 23901.1Skamil 23911.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 23921.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 23931.1Skamil 23941.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 23951.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 23961.1Skamil 23971.13Schristos DPRINTF("Detect that tracee is zombie\n"); 23981.51Skamil if (notimeout) 23991.26Skamil await_zombie_raw(tracee, 0); 24001.26Skamil else 24011.26Skamil await_zombie(tracee); 24021.1Skamil 24031.13Schristos DPRINTF("Assert that there is no status about tracee %d - " 24041.1Skamil "Tracer must detect zombie first - calling %s()\n", tracee, 24051.1Skamil TWAIT_FNAME); 24061.1Skamil TWAIT_REQUIRE_SUCCESS( 24071.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 24081.1Skamil 24091.51Skamil if (unrelated) { 24101.51Skamil DPRINTF("Resume the tracer and let it detect exited tracee\n"); 24111.51Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 24121.51Skamil } else { 24131.51Skamil DPRINTF("Tell the tracer child should have exited\n"); 24141.51Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 24151.51Skamil DPRINTF("Wait for tracer to finish its job and exit - calling " 24161.59Skamil "%s()\n", TWAIT_FNAME); 24171.51Skamil 24181.51Skamil DPRINTF("Wait from tracer child to complete waiting for " 24191.59Skamil "tracee\n"); 24201.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 24211.51Skamil tracer); 24221.1Skamil 24231.51Skamil validate_status_exited(status, exitval_tracer); 24241.51Skamil } 24251.1Skamil 24261.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 24271.1Skamil TWAIT_FNAME); 24281.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24291.1Skamil 24301.1Skamil validate_status_exited(status, exitval_tracee); 24311.1Skamil 24321.1Skamil msg_close(&parent_tracer); 24331.1Skamil msg_close(&parent_tracee); 24341.1Skamil} 24351.26Skamil 24361.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent); 24371.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc) 24381.51Skamil{ 24391.51Skamil atf_tc_set_md_var(tc, "descr", 24401.51Skamil "Assert that tracer sees process termination before the parent"); 24411.51Skamil} 24421.51Skamil 24431.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc) 24441.26Skamil{ 24451.26Skamil 24461.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, false, false); 24471.26Skamil} 24481.26Skamil 24491.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates); 24501.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc) 24511.1Skamil{ 24521.1Skamil atf_tc_set_md_var(tc, "descr", 24531.51Skamil "Assert that await_zombie() in attach1 always finds a single " 24541.51Skamil "process and no other error is reported"); 24551.1Skamil} 24561.1Skamil 24571.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc) 24581.1Skamil{ 24591.51Skamil time_t start, end; 24601.51Skamil double diff; 24611.51Skamil unsigned long N = 0; 24621.1Skamil 24631.51Skamil /* 24641.51Skamil * Reuse this test with tracer_sees_terminaton_before_the_parent_raw(). 24651.51Skamil * This test body isn't specific to this race, however it's just good 24661.51Skamil * enough for this purposes, no need to invent a dedicated code flow. 24671.51Skamil */ 24681.1Skamil 24691.51Skamil start = time(NULL); 24701.51Skamil while (true) { 24711.51Skamil DPRINTF("Step: %lu\n", N); 24721.67Skamil tracer_sees_terminaton_before_the_parent_raw(true, false, 24731.67Skamil false); 24741.51Skamil end = time(NULL); 24751.51Skamil diff = difftime(end, start); 24761.51Skamil if (diff >= 5.0) 24771.51Skamil break; 24781.51Skamil ++N; 24791.1Skamil } 24801.51Skamil DPRINTF("Iterations: %lu\n", N); 24811.51Skamil} 24821.1Skamil 24831.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent); 24841.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc) 24851.51Skamil{ 24861.51Skamil atf_tc_set_md_var(tc, "descr", 24871.51Skamil "Assert that tracer sees process termination before the parent"); 24881.51Skamil} 24891.1Skamil 24901.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc) 24911.51Skamil{ 24921.1Skamil 24931.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, false); 24941.67Skamil} 24951.67Skamil 24961.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process); 24971.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc) 24981.67Skamil{ 24991.67Skamil atf_tc_set_md_var(tc, "descr", 25001.67Skamil "Assert that tracer can attach to an unrelated stopped process"); 25011.67Skamil} 25021.67Skamil 25031.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc) 25041.67Skamil{ 25051.67Skamil 25061.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, true); 25071.1Skamil} 25081.1Skamil#endif 25091.1Skamil 25101.51Skamil/// ---------------------------------------------------------------------------- 25111.51Skamil 25121.66Skamilstatic void 25131.66Skamilparent_attach_to_its_child(bool stopped) 25141.1Skamil{ 25151.1Skamil struct msg_fds parent_tracee; 25161.1Skamil const int exitval_tracee = 5; 25171.1Skamil pid_t tracee, wpid; 25181.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 25191.1Skamil#if defined(TWAIT_HAVE_STATUS) 25201.1Skamil int status; 25211.1Skamil#endif 25221.1Skamil 25231.13Schristos DPRINTF("Spawn tracee\n"); 25241.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 25251.1Skamil tracee = atf_utils_fork(); 25261.1Skamil if (tracee == 0) { 25271.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 25281.13Schristos DPRINTF("Parent should now attach to tracee\n"); 25291.1Skamil 25301.66Skamil if (stopped) { 25311.66Skamil DPRINTF("Stop self PID %d\n", getpid()); 25321.66Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 25331.66Skamil } 25341.66Skamil 25351.1Skamil CHILD_FROM_PARENT("Message 2", parent_tracee, msg); 25361.1Skamil /* Wait for message from the parent */ 25371.1Skamil _exit(exitval_tracee); 25381.1Skamil } 25391.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 25401.57Skamil 25411.66Skamil if (stopped) { 25421.66Skamil DPRINTF("Await for a stopped tracee PID %d\n", tracee); 25431.66Skamil await_stopped(tracee); 25441.66Skamil } 25451.66Skamil 25461.13Schristos DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee); 25471.13Schristos SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 25481.1Skamil 25491.13Schristos DPRINTF("Wait for the stopped tracee process with %s()\n", 25501.1Skamil TWAIT_FNAME); 25511.1Skamil TWAIT_REQUIRE_SUCCESS( 25521.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25531.1Skamil 25541.1Skamil validate_status_stopped(status, SIGSTOP); 25551.1Skamil 25561.13Schristos DPRINTF("Resume tracee with PT_CONTINUE\n"); 25571.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 25581.1Skamil 25591.13Schristos DPRINTF("Let the tracee exit now\n"); 25601.1Skamil PARENT_TO_CHILD("Message 2", parent_tracee, msg); 25611.1Skamil 25621.13Schristos DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME); 25631.1Skamil TWAIT_REQUIRE_SUCCESS( 25641.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25651.1Skamil 25661.1Skamil validate_status_exited(status, exitval_tracee); 25671.1Skamil 25681.13Schristos DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME); 25691.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 25701.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0)); 25711.1Skamil 25721.1Skamil msg_close(&parent_tracee); 25731.1Skamil} 25741.1Skamil 25751.66SkamilATF_TC(parent_attach_to_its_child); 25761.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc) 25771.66Skamil{ 25781.66Skamil atf_tc_set_md_var(tc, "descr", 25791.66Skamil "Assert that tracer parent can PT_ATTACH to its child"); 25801.66Skamil} 25811.66Skamil 25821.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc) 25831.66Skamil{ 25841.66Skamil 25851.66Skamil parent_attach_to_its_child(false); 25861.66Skamil} 25871.66Skamil 25881.66SkamilATF_TC(parent_attach_to_its_stopped_child); 25891.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc) 25901.66Skamil{ 25911.66Skamil atf_tc_set_md_var(tc, "descr", 25921.66Skamil "Assert that tracer parent can PT_ATTACH to its stopped child"); 25931.66Skamil} 25941.66Skamil 25951.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc) 25961.66Skamil{ 25971.66Skamil 25981.66Skamil parent_attach_to_its_child(true); 25991.66Skamil} 26001.66Skamil 26011.51Skamil/// ---------------------------------------------------------------------------- 26021.51Skamil 26031.65Skamilstatic void 26041.65Skamilchild_attach_to_its_parent(bool stopped) 26051.1Skamil{ 26061.1Skamil struct msg_fds parent_tracee; 26071.1Skamil const int exitval_tracer = 5; 26081.1Skamil pid_t tracer, wpid; 26091.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 26101.1Skamil#if defined(TWAIT_HAVE_STATUS) 26111.1Skamil int status; 26121.1Skamil#endif 26131.1Skamil 26141.13Schristos DPRINTF("Spawn tracer\n"); 26151.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 26161.1Skamil tracer = atf_utils_fork(); 26171.1Skamil if (tracer == 0) { 26181.1Skamil /* Wait for message from the parent */ 26191.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 26201.1Skamil 26211.65Skamil if (stopped) { 26221.65Skamil DPRINTF("Await for a stopped parent PID %d\n", 26231.65Skamil getppid()); 26241.65Skamil await_stopped(getppid()); 26251.65Skamil } 26261.65Skamil 26271.13Schristos DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n", 26281.1Skamil getppid()); 26291.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1); 26301.1Skamil 26311.13Schristos DPRINTF("Wait for the stopped parent process with %s()\n", 26321.1Skamil TWAIT_FNAME); 26331.1Skamil FORKEE_REQUIRE_SUCCESS( 26341.1Skamil wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid()); 26351.1Skamil 26361.1Skamil forkee_status_stopped(status, SIGSTOP); 26371.1Skamil 26381.13Schristos DPRINTF("Resume parent with PT_DETACH\n"); 26391.1Skamil FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0) 26401.1Skamil != -1); 26411.1Skamil 26421.1Skamil /* Tell parent we are ready */ 26431.1Skamil CHILD_TO_PARENT("Message 1", parent_tracee, msg); 26441.1Skamil 26451.1Skamil _exit(exitval_tracer); 26461.1Skamil } 26471.1Skamil 26481.13Schristos DPRINTF("Wait for the tracer to become ready\n"); 26491.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 26501.65Skamil 26511.65Skamil if (stopped) { 26521.65Skamil DPRINTF("Stop self PID %d\n", getpid()); 26531.65Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 26541.65Skamil } 26551.65Skamil 26561.13Schristos DPRINTF("Allow the tracer to exit now\n"); 26571.1Skamil PARENT_FROM_CHILD("Message 1", parent_tracee, msg); 26581.1Skamil 26591.13Schristos DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME); 26601.1Skamil TWAIT_REQUIRE_SUCCESS( 26611.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 26621.1Skamil 26631.1Skamil validate_status_exited(status, exitval_tracer); 26641.1Skamil 26651.13Schristos DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME); 26661.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 26671.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0)); 26681.1Skamil 26691.1Skamil msg_close(&parent_tracee); 26701.1Skamil} 26711.1Skamil 26721.65SkamilATF_TC(child_attach_to_its_parent); 26731.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc) 26741.65Skamil{ 26751.65Skamil atf_tc_set_md_var(tc, "descr", 26761.65Skamil "Assert that tracer child can PT_ATTACH to its parent"); 26771.65Skamil} 26781.65Skamil 26791.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc) 26801.65Skamil{ 26811.65Skamil 26821.65Skamil child_attach_to_its_parent(false); 26831.65Skamil} 26841.65Skamil 26851.65SkamilATF_TC(child_attach_to_its_stopped_parent); 26861.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc) 26871.65Skamil{ 26881.65Skamil atf_tc_set_md_var(tc, "descr", 26891.65Skamil "Assert that tracer child can PT_ATTACH to its stopped parent"); 26901.65Skamil} 26911.65Skamil 26921.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc) 26931.65Skamil{ 26941.65Skamil /* 26951.65Skamil * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as 26961.65Skamil * this causes a pipe (established from atf-run) to be broken. 26971.65Skamil * atf-run uses this mechanism to monitor whether a test is alive. 26981.65Skamil * 26991.65Skamil * As a workaround spawn this test as a subprocess. 27001.65Skamil */ 27011.65Skamil 27021.65Skamil const int exitval = 15; 27031.65Skamil pid_t child, wpid; 27041.65Skamil#if defined(TWAIT_HAVE_STATUS) 27051.65Skamil int status; 27061.65Skamil#endif 27071.65Skamil 27081.65Skamil SYSCALL_REQUIRE((child = fork()) != -1); 27091.65Skamil if (child == 0) { 27101.65Skamil child_attach_to_its_parent(true); 27111.65Skamil _exit(exitval); 27121.65Skamil } else { 27131.65Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 27141.65Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 27151.65Skamil 27161.65Skamil validate_status_exited(status, exitval); 27171.65Skamil 27181.65Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 27191.65Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 27201.65Skamil } 27211.65Skamil} 27221.65Skamil 27231.51Skamil/// ---------------------------------------------------------------------------- 27241.51Skamil 27251.1Skamil#if defined(TWAIT_HAVE_PID) 27261.1Skamil 27271.51Skamilenum tracee_sees_its_original_parent_type { 27281.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 27291.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 27301.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS 27311.51Skamil}; 27321.51Skamil 27331.51Skamilstatic void 27341.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type) 27351.1Skamil{ 27361.1Skamil struct msg_fds parent_tracer, parent_tracee; 27371.1Skamil const int exitval_tracee = 5; 27381.1Skamil const int exitval_tracer = 10; 27391.1Skamil pid_t parent, tracee, tracer, wpid; 27401.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 27411.1Skamil#if defined(TWAIT_HAVE_STATUS) 27421.1Skamil int status; 27431.1Skamil#endif 27441.51Skamil /* sysctl(3) - kinfo_proc2 */ 27451.51Skamil int name[CTL_MAXNAME]; 27461.51Skamil struct kinfo_proc2 kp; 27471.51Skamil size_t len = sizeof(kp); 27481.51Skamil unsigned int namelen; 27491.51Skamil 27501.51Skamil /* procfs - status */ 27511.51Skamil FILE *fp; 27521.51Skamil struct stat st; 27531.51Skamil const char *fname = "/proc/curproc/status"; 27541.51Skamil char s_executable[MAXPATHLEN]; 27551.51Skamil int s_pid, s_ppid; 27561.51Skamil int rv; 27571.51Skamil 27581.51Skamil if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) { 27591.61Skre SYSCALL_REQUIRE( 27601.61Skre (rv = stat(fname, &st)) == 0 || (errno == ENOENT)); 27611.61Skre if (rv != 0) 27621.51Skamil atf_tc_skip("/proc/curproc/status not found"); 27631.51Skamil } 27641.1Skamil 27651.13Schristos DPRINTF("Spawn tracee\n"); 27661.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 27671.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 27681.1Skamil tracee = atf_utils_fork(); 27691.1Skamil if (tracee == 0) { 27701.1Skamil parent = getppid(); 27711.1Skamil 27721.1Skamil /* Emit message to the parent */ 27731.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 27741.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 27751.1Skamil 27761.51Skamil switch (type) { 27771.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID: 27781.51Skamil FORKEE_ASSERT_EQ(parent, getppid()); 27791.51Skamil break; 27801.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2: 27811.51Skamil namelen = 0; 27821.51Skamil name[namelen++] = CTL_KERN; 27831.51Skamil name[namelen++] = KERN_PROC2; 27841.51Skamil name[namelen++] = KERN_PROC_PID; 27851.51Skamil name[namelen++] = getpid(); 27861.51Skamil name[namelen++] = len; 27871.51Skamil name[namelen++] = 1; 27881.51Skamil 27891.61Skre FORKEE_ASSERT_EQ( 27901.61Skre sysctl(name, namelen, &kp, &len, NULL, 0), 0); 27911.51Skamil FORKEE_ASSERT_EQ(parent, kp.p_ppid); 27921.51Skamil break; 27931.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS: 27941.51Skamil /* 27951.51Skamil * Format: 27961.51Skamil * EXECUTABLE PID PPID ... 27971.51Skamil */ 27981.51Skamil FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL); 27991.51Skamil fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid); 28001.51Skamil FORKEE_ASSERT_EQ(fclose(fp), 0); 28011.51Skamil FORKEE_ASSERT_EQ(parent, s_ppid); 28021.51Skamil break; 28031.51Skamil } 28041.1Skamil 28051.1Skamil _exit(exitval_tracee); 28061.1Skamil } 28071.13Schristos DPRINTF("Wait for child to record its parent identifier (pid)\n"); 28081.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 28091.1Skamil 28101.13Schristos DPRINTF("Spawn debugger\n"); 28111.1Skamil tracer = atf_utils_fork(); 28121.1Skamil if (tracer == 0) { 28131.1Skamil /* No IPC to communicate with the child */ 28141.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 28151.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 28161.1Skamil 28171.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 28181.1Skamil FORKEE_REQUIRE_SUCCESS( 28191.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28201.1Skamil 28211.1Skamil forkee_status_stopped(status, SIGSTOP); 28221.1Skamil 28231.1Skamil /* Resume tracee with PT_CONTINUE */ 28241.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 28251.1Skamil 28261.1Skamil /* Inform parent that tracer has attached to tracee */ 28271.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 28281.1Skamil 28291.1Skamil /* Wait for parent to tell use that tracee should have exited */ 28301.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 28311.1Skamil 28321.1Skamil /* Wait for tracee and assert that it exited */ 28331.1Skamil FORKEE_REQUIRE_SUCCESS( 28341.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28351.1Skamil 28361.1Skamil forkee_status_exited(status, exitval_tracee); 28371.1Skamil 28381.13Schristos DPRINTF("Before exiting of the tracer process\n"); 28391.1Skamil _exit(exitval_tracer); 28401.1Skamil } 28411.1Skamil 28421.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 28431.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 28441.1Skamil 28451.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 28461.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 28471.1Skamil 28481.13Schristos DPRINTF("Detect that tracee is zombie\n"); 28491.1Skamil await_zombie(tracee); 28501.1Skamil 28511.13Schristos DPRINTF("Assert that there is no status about tracee - " 28521.1Skamil "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME); 28531.1Skamil TWAIT_REQUIRE_SUCCESS( 28541.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 28551.1Skamil 28561.13Schristos DPRINTF("Tell the tracer child should have exited\n"); 28571.1Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 28581.1Skamil 28591.13Schristos DPRINTF("Wait from tracer child to complete waiting for tracee\n"); 28601.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 28611.1Skamil tracer); 28621.1Skamil 28631.1Skamil validate_status_exited(status, exitval_tracer); 28641.1Skamil 28651.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 28661.1Skamil TWAIT_FNAME); 28671.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 28681.1Skamil tracee); 28691.1Skamil 28701.1Skamil validate_status_exited(status, exitval_tracee); 28711.1Skamil 28721.1Skamil msg_close(&parent_tracer); 28731.1Skamil msg_close(&parent_tracee); 28741.1Skamil} 28751.1Skamil 28761.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr) \ 28771.61SkreATF_TC(test); \ 28781.61SkreATF_TC_HEAD(test, tc) \ 28791.61Skre{ \ 28801.61Skre atf_tc_set_md_var(tc, "descr", \ 28811.61Skre "Assert that tracee sees its original parent when being traced " \ 28821.61Skre "(check " descr ")"); \ 28831.61Skre} \ 28841.61Skre \ 28851.61SkreATF_TC_BODY(test, tc) \ 28861.61Skre{ \ 28871.61Skre \ 28881.61Skre tracee_sees_its_original_parent(type); \ 28891.1Skamil} 28901.1Skamil 28911.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 28921.51Skamil tracee_sees_its_original_parent_getppid, 28931.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 28941.51Skamil "getppid(2)"); 28951.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 28961.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2, 28971.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 28981.51Skamil "sysctl(3) and kinfo_proc2"); 28991.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29001.51Skamil tracee_sees_its_original_parent_procfs_status, 29011.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS, 29021.51Skamil "the status file in procfs"); 29031.1Skamil#endif 29041.1Skamil 29051.51Skamil/// ---------------------------------------------------------------------------- 29061.1Skamil 29071.53Skamilstatic void 29081.53Skamileventmask_preserved(int event) 29091.1Skamil{ 29101.1Skamil const int exitval = 5; 29111.1Skamil const int sigval = SIGSTOP; 29121.1Skamil pid_t child, wpid; 29131.1Skamil#if defined(TWAIT_HAVE_STATUS) 29141.1Skamil int status; 29151.1Skamil#endif 29161.1Skamil ptrace_event_t set_event, get_event; 29171.1Skamil const int len = sizeof(ptrace_event_t); 29181.1Skamil 29191.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 29201.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 29211.1Skamil if (child == 0) { 29221.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 29231.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 29241.1Skamil 29251.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 29261.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 29271.1Skamil 29281.13Schristos DPRINTF("Before exiting of the child process\n"); 29291.1Skamil _exit(exitval); 29301.1Skamil } 29311.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 29321.1Skamil 29331.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29341.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29351.1Skamil 29361.1Skamil validate_status_stopped(status, sigval); 29371.1Skamil 29381.53Skamil set_event.pe_set_event = event; 29391.61Skre SYSCALL_REQUIRE( 29401.61Skre ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); 29411.61Skre SYSCALL_REQUIRE( 29421.61Skre ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); 29431.1Skamil ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); 29441.1Skamil 29451.13Schristos DPRINTF("Before resuming the child process where it left off and " 29461.1Skamil "without signal to be sent\n"); 29471.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 29481.1Skamil 29491.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29501.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29511.1Skamil 29521.1Skamil validate_status_exited(status, exitval); 29531.1Skamil 29541.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29551.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 29561.1Skamil} 29571.1Skamil 29581.61Skre#define EVENTMASK_PRESERVED(test, event) \ 29591.61SkreATF_TC(test); \ 29601.61SkreATF_TC_HEAD(test, tc) \ 29611.61Skre{ \ 29621.61Skre atf_tc_set_md_var(tc, "descr", \ 29631.61Skre "Verify that eventmask " #event " is preserved"); \ 29641.61Skre} \ 29651.61Skre \ 29661.61SkreATF_TC_BODY(test, tc) \ 29671.61Skre{ \ 29681.61Skre \ 29691.61Skre eventmask_preserved(event); \ 29701.1Skamil} 29711.1Skamil 29721.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0) 29731.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK) 29741.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK) 29751.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE) 29761.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE) 29771.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT) 29781.1Skamil 29791.53Skamil/// ---------------------------------------------------------------------------- 29801.1Skamil 29811.28Skamilstatic void 29821.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork, 29831.105Skamil bool trackvforkdone) 29841.1Skamil{ 29851.1Skamil const int exitval = 5; 29861.1Skamil const int exitval2 = 15; 29871.1Skamil const int sigval = SIGSTOP; 29881.31Skamil pid_t child, child2 = 0, wpid; 29891.1Skamil#if defined(TWAIT_HAVE_STATUS) 29901.1Skamil int status; 29911.1Skamil#endif 29921.1Skamil ptrace_state_t state; 29931.1Skamil const int slen = sizeof(state); 29941.1Skamil ptrace_event_t event; 29951.1Skamil const int elen = sizeof(event); 29961.1Skamil 29971.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 29981.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 29991.1Skamil if (child == 0) { 30001.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 30011.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 30021.1Skamil 30031.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 30041.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 30051.1Skamil 30061.30Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 30071.1Skamil 30081.1Skamil if (child2 == 0) 30091.1Skamil _exit(exitval2); 30101.1Skamil 30111.1Skamil FORKEE_REQUIRE_SUCCESS 30121.1Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 30131.1Skamil 30141.1Skamil forkee_status_exited(status, exitval2); 30151.1Skamil 30161.13Schristos DPRINTF("Before exiting of the child process\n"); 30171.1Skamil _exit(exitval); 30181.1Skamil } 30191.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 30201.1Skamil 30211.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 30221.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 30231.1Skamil 30241.1Skamil validate_status_stopped(status, sigval); 30251.1Skamil 30261.30Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 30271.61Skre trackfork ? "|PTRACE_FORK" : "", 30281.61Skre trackvfork ? "|PTRACE_VFORK" : "", 30291.61Skre trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 30301.30Skamil event.pe_set_event = 0; 30311.30Skamil if (trackfork) 30321.30Skamil event.pe_set_event |= PTRACE_FORK; 30331.30Skamil if (trackvfork) 30341.30Skamil event.pe_set_event |= PTRACE_VFORK; 30351.30Skamil if (trackvforkdone) 30361.30Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 30371.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 30381.1Skamil 30391.13Schristos DPRINTF("Before resuming the child process where it left off and " 30401.1Skamil "without signal to be sent\n"); 30411.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 30421.1Skamil 30431.29Skamil#if defined(TWAIT_HAVE_PID) 30441.31Skamil if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) { 30451.29Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 30461.61Skre child); 30471.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 30481.61Skre child); 30491.1Skamil 30501.29Skamil validate_status_stopped(status, SIGTRAP); 30511.1Skamil 30521.61Skre SYSCALL_REQUIRE( 30531.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 30541.31Skamil if (trackfork && fn == fork) { 30551.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 30561.30Skamil PTRACE_FORK); 30571.30Skamil } 30581.31Skamil if (trackvfork && fn == vfork) { 30591.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 30601.30Skamil PTRACE_VFORK); 30611.30Skamil } 30621.29Skamil 30631.29Skamil child2 = state.pe_other_pid; 30641.30Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 30651.29Skamil 30661.29Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 30671.61Skre "%d\n", TWAIT_FNAME, child2, child); 30681.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 30691.29Skamil child2); 30701.1Skamil 30711.29Skamil validate_status_stopped(status, SIGTRAP); 30721.1Skamil 30731.61Skre SYSCALL_REQUIRE( 30741.61Skre ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 30751.31Skamil if (trackfork && fn == fork) { 30761.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 30771.30Skamil PTRACE_FORK); 30781.30Skamil } 30791.31Skamil if (trackvfork && fn == vfork) { 30801.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 30811.30Skamil PTRACE_VFORK); 30821.30Skamil } 30831.30Skamil 30841.29Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 30851.29Skamil 30861.29Skamil DPRINTF("Before resuming the forkee process where it left off " 30871.29Skamil "and without signal to be sent\n"); 30881.61Skre SYSCALL_REQUIRE( 30891.61Skre ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 30901.29Skamil 30911.29Skamil DPRINTF("Before resuming the child process where it left off " 30921.61Skre "and without signal to be sent\n"); 30931.29Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 30941.30Skamil } 30951.30Skamil#endif 30961.30Skamil 30971.31Skamil if (trackvforkdone && fn == vfork) { 30981.30Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 30991.61Skre child); 31001.61Skre TWAIT_REQUIRE_SUCCESS( 31011.61Skre wpid = TWAIT_GENERIC(child, &status, 0), child); 31021.30Skamil 31031.30Skamil validate_status_stopped(status, SIGTRAP); 31041.30Skamil 31051.61Skre SYSCALL_REQUIRE( 31061.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 31071.30Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 31081.30Skamil 31091.30Skamil child2 = state.pe_other_pid; 31101.30Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 31111.61Skre child2); 31121.30Skamil 31131.30Skamil DPRINTF("Before resuming the child process where it left off " 31141.61Skre "and without signal to be sent\n"); 31151.30Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31161.30Skamil } 31171.29Skamil 31181.30Skamil#if defined(TWAIT_HAVE_PID) 31191.31Skamil if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) { 31201.29Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 31211.61Skre "\n", TWAIT_FNAME); 31221.61Skre TWAIT_REQUIRE_SUCCESS( 31231.61Skre wpid = TWAIT_GENERIC(child2, &status, 0), child2); 31241.29Skamil 31251.29Skamil validate_status_exited(status, exitval2); 31261.29Skamil 31271.29Skamil DPRINTF("Before calling %s() for the forkee - expected no " 31281.61Skre "process\n", TWAIT_FNAME); 31291.29Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 31301.29Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 31311.29Skamil } 31321.29Skamil#endif 31331.1Skamil 31341.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 31351.1Skamil "SIGCHLD\n", TWAIT_FNAME); 31361.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31371.1Skamil 31381.1Skamil validate_status_stopped(status, SIGCHLD); 31391.1Skamil 31401.13Schristos DPRINTF("Before resuming the child process where it left off and " 31411.1Skamil "without signal to be sent\n"); 31421.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31431.1Skamil 31441.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 31451.1Skamil TWAIT_FNAME); 31461.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31471.1Skamil 31481.1Skamil validate_status_exited(status, exitval); 31491.1Skamil 31501.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 31511.1Skamil TWAIT_FNAME); 31521.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 31531.1Skamil} 31541.28Skamil 31551.105Skamil#define FORK_TEST(name,fun,tfork,tvfork,tvforkdone) \ 31561.61SkreATF_TC(name); \ 31571.61SkreATF_TC_HEAD(name, tc) \ 31581.61Skre{ \ 31591.105Skamil atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) " \ 31601.105Skamil "called with 0%s%s%s in EVENT_MASK", \ 31611.105Skamil tfork ? "|PTRACE_FORK" : "", \ 31621.105Skamil tvfork ? "|PTRACE_VFORK" : "", \ 31631.105Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 31641.61Skre} \ 31651.61Skre \ 31661.61SkreATF_TC_BODY(name, tc) \ 31671.61Skre{ \ 31681.61Skre \ 31691.105Skamil fork_body(fun, tfork, tvfork, tvforkdone); \ 31701.32Skamil} 31711.32Skamil 31721.105SkamilFORK_TEST(fork1, fork, false, false, false) 31731.31Skamil#if defined(TWAIT_HAVE_PID) 31741.105SkamilFORK_TEST(fork2, fork, true, false, false) 31751.105SkamilFORK_TEST(fork3, fork, false, true, false) 31761.105SkamilFORK_TEST(fork4, fork, true, true, false) 31771.31Skamil#endif 31781.105SkamilFORK_TEST(fork5, fork, false, false, true) 31791.31Skamil#if defined(TWAIT_HAVE_PID) 31801.105SkamilFORK_TEST(fork6, fork, true, false, true) 31811.105SkamilFORK_TEST(fork7, fork, false, true, true) 31821.105SkamilFORK_TEST(fork8, fork, true, true, true) 31831.31Skamil#endif 31841.1Skamil 31851.110Skamil#if TEST_VFORK_ENABLED 31861.105SkamilFORK_TEST(vfork1, vfork, false, false, false) 31871.31Skamil#if defined(TWAIT_HAVE_PID) 31881.105SkamilFORK_TEST(vfork2, vfork, true, false, false) 31891.105SkamilFORK_TEST(vfork3, vfork, false, true, false) 31901.105SkamilFORK_TEST(vfork4, vfork, true, true, false) 31911.31Skamil#endif 31921.105SkamilFORK_TEST(vfork5, vfork, false, false, true) 31931.31Skamil#if defined(TWAIT_HAVE_PID) 31941.105SkamilFORK_TEST(vfork6, vfork, true, false, true) 31951.105SkamilFORK_TEST(vfork7, vfork, false, true, true) 31961.105SkamilFORK_TEST(vfork8, vfork, true, true, true) 31971.31Skamil#endif 31981.110Skamil#endif 31991.31Skamil 32001.54Skamil/// ---------------------------------------------------------------------------- 32011.31Skamil 32021.110Skamil#if TEST_VFORK_ENABLED 32031.108Skamilstatic void 32041.108Skamiltraceme_vfork_fork_body(pid_t (*fn)(void)) 32051.108Skamil{ 32061.108Skamil const int exitval = 5; 32071.108Skamil const int exitval2 = 15; 32081.108Skamil pid_t child, child2 = 0, wpid; 32091.108Skamil#if defined(TWAIT_HAVE_STATUS) 32101.108Skamil int status; 32111.108Skamil#endif 32121.108Skamil 32131.108Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 32141.108Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 32151.108Skamil if (child == 0) { 32161.108Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 32171.108Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 32181.108Skamil 32191.108Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 32201.108Skamil 32211.108Skamil if (child2 == 0) 32221.108Skamil _exit(exitval2); 32231.108Skamil 32241.108Skamil FORKEE_REQUIRE_SUCCESS 32251.108Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 32261.108Skamil 32271.108Skamil forkee_status_exited(status, exitval2); 32281.108Skamil 32291.108Skamil DPRINTF("Before exiting of the child process\n"); 32301.108Skamil _exit(exitval); 32311.108Skamil } 32321.108Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 32331.108Skamil 32341.108Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 32351.108Skamil TWAIT_FNAME); 32361.108Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 32371.108Skamil 32381.108Skamil validate_status_exited(status, exitval); 32391.108Skamil 32401.108Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 32411.108Skamil TWAIT_FNAME); 32421.108Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 32431.108Skamil} 32441.108Skamil 32451.108Skamil#define TRACEME_VFORK_FORK_TEST(name,fun) \ 32461.108SkamilATF_TC(name); \ 32471.108SkamilATF_TC_HEAD(name, tc) \ 32481.108Skamil{ \ 32491.108Skamil atf_tc_set_md_var(tc, "descr", "Verify " #fun "(2) " \ 32501.108Skamil "called from vfork(2)ed child"); \ 32511.108Skamil} \ 32521.108Skamil \ 32531.108SkamilATF_TC_BODY(name, tc) \ 32541.108Skamil{ \ 32551.108Skamil \ 32561.108Skamil traceme_vfork_fork_body(fun); \ 32571.108Skamil} 32581.108Skamil 32591.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_fork, fork) 32601.108SkamilTRACEME_VFORK_FORK_TEST(traceme_vfork_vfork, vfork) 32611.110Skamil#endif 32621.108Skamil 32631.108Skamil/// ---------------------------------------------------------------------------- 32641.108Skamil 32651.54Skamilenum bytes_transfer_type { 32661.54Skamil BYTES_TRANSFER_DATA, 32671.54Skamil BYTES_TRANSFER_DATAIO, 32681.54Skamil BYTES_TRANSFER_TEXT, 32691.54Skamil BYTES_TRANSFER_TEXTIO, 32701.54Skamil BYTES_TRANSFER_AUXV 32711.54Skamil}; 32721.31Skamil 32731.54Skamilstatic int __used 32741.54Skamilbytes_transfer_dummy(int a, int b, int c, int d) 32751.54Skamil{ 32761.54Skamil int e, f, g, h; 32771.1Skamil 32781.54Skamil a *= 4; 32791.54Skamil b += 3; 32801.54Skamil c -= 2; 32811.54Skamil d /= 1; 32821.1Skamil 32831.54Skamil e = strtol("10", NULL, 10); 32841.54Skamil f = strtol("20", NULL, 10); 32851.54Skamil g = strtol("30", NULL, 10); 32861.54Skamil h = strtol("40", NULL, 10); 32871.1Skamil 32881.54Skamil return (a + b * c - d) + (e * f - g / h); 32891.1Skamil} 32901.1Skamil 32911.54Skamilstatic void 32921.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type) 32931.1Skamil{ 32941.1Skamil const int exitval = 5; 32951.1Skamil const int sigval = SIGSTOP; 32961.1Skamil pid_t child, wpid; 32971.54Skamil bool skip = false; 32981.1Skamil 32991.54Skamil int lookup_me = 0; 33001.54Skamil uint8_t lookup_me8 = 0; 33011.54Skamil uint16_t lookup_me16 = 0; 33021.54Skamil uint32_t lookup_me32 = 0; 33031.54Skamil uint64_t lookup_me64 = 0; 33041.1Skamil 33051.54Skamil int magic = 0x13579246; 33061.54Skamil uint8_t magic8 = 0xab; 33071.54Skamil uint16_t magic16 = 0x1234; 33081.54Skamil uint32_t magic32 = 0x98765432; 33091.54Skamil uint64_t magic64 = 0xabcdef0123456789; 33101.1Skamil 33111.54Skamil struct ptrace_io_desc io; 33121.1Skamil#if defined(TWAIT_HAVE_STATUS) 33131.1Skamil int status; 33141.1Skamil#endif 33151.60Skre /* 513 is just enough, for the purposes of ATF it's good enough */ 33161.60Skre AuxInfo ai[513], *aip; 33171.55Schristos 33181.55Schristos ATF_REQUIRE(size < sizeof(ai)); 33191.1Skamil 33201.54Skamil /* Prepare variables for .TEXT transfers */ 33211.54Skamil switch (type) { 33221.54Skamil case BYTES_TRANSFER_TEXT: 33231.54Skamil memcpy(&magic, bytes_transfer_dummy, sizeof(magic)); 33241.54Skamil break; 33251.54Skamil case BYTES_TRANSFER_TEXTIO: 33261.54Skamil switch (size) { 33271.54Skamil case 8: 33281.54Skamil memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8)); 33291.54Skamil break; 33301.54Skamil case 16: 33311.54Skamil memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16)); 33321.54Skamil break; 33331.54Skamil case 32: 33341.54Skamil memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32)); 33351.54Skamil break; 33361.54Skamil case 64: 33371.54Skamil memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64)); 33381.54Skamil break; 33391.54Skamil } 33401.54Skamil break; 33411.54Skamil default: 33421.54Skamil break; 33431.54Skamil } 33441.1Skamil 33451.54Skamil /* Prepare variables for PIOD and AUXV transfers */ 33461.54Skamil switch (type) { 33471.54Skamil case BYTES_TRANSFER_TEXTIO: 33481.54Skamil case BYTES_TRANSFER_DATAIO: 33491.54Skamil io.piod_op = operation; 33501.54Skamil switch (size) { 33511.54Skamil case 8: 33521.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 33531.54Skamil (void *)bytes_transfer_dummy : 33541.54Skamil &lookup_me8; 33551.54Skamil io.piod_addr = &lookup_me8; 33561.54Skamil io.piod_len = sizeof(lookup_me8); 33571.54Skamil break; 33581.54Skamil case 16: 33591.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 33601.54Skamil (void *)bytes_transfer_dummy : 33611.54Skamil &lookup_me16; 33621.54Skamil io.piod_addr = &lookup_me16; 33631.54Skamil io.piod_len = sizeof(lookup_me16); 33641.54Skamil break; 33651.54Skamil case 32: 33661.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 33671.54Skamil (void *)bytes_transfer_dummy : 33681.54Skamil &lookup_me32; 33691.54Skamil io.piod_addr = &lookup_me32; 33701.54Skamil io.piod_len = sizeof(lookup_me32); 33711.54Skamil break; 33721.54Skamil case 64: 33731.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 33741.54Skamil (void *)bytes_transfer_dummy : 33751.54Skamil &lookup_me64; 33761.54Skamil io.piod_addr = &lookup_me64; 33771.54Skamil io.piod_len = sizeof(lookup_me64); 33781.54Skamil break; 33791.54Skamil default: 33801.54Skamil break; 33811.54Skamil } 33821.54Skamil break; 33831.54Skamil case BYTES_TRANSFER_AUXV: 33841.54Skamil io.piod_op = operation; 33851.54Skamil io.piod_offs = 0; 33861.54Skamil io.piod_addr = ai; 33871.54Skamil io.piod_len = size; 33881.54Skamil break; 33891.54Skamil default: 33901.54Skamil break; 33911.1Skamil } 33921.1Skamil 33931.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 33941.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 33951.1Skamil if (child == 0) { 33961.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 33971.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 33981.1Skamil 33991.54Skamil switch (type) { 34001.54Skamil case BYTES_TRANSFER_DATA: 34011.54Skamil switch (operation) { 34021.54Skamil case PT_READ_D: 34031.54Skamil case PT_READ_I: 34041.54Skamil lookup_me = magic; 34051.54Skamil break; 34061.54Skamil default: 34071.54Skamil break; 34081.54Skamil } 34091.54Skamil break; 34101.54Skamil case BYTES_TRANSFER_DATAIO: 34111.54Skamil switch (operation) { 34121.54Skamil case PIOD_READ_D: 34131.54Skamil case PIOD_READ_I: 34141.54Skamil switch (size) { 34151.54Skamil case 8: 34161.54Skamil lookup_me8 = magic8; 34171.54Skamil break; 34181.54Skamil case 16: 34191.54Skamil lookup_me16 = magic16; 34201.54Skamil break; 34211.54Skamil case 32: 34221.54Skamil lookup_me32 = magic32; 34231.54Skamil break; 34241.54Skamil case 64: 34251.54Skamil lookup_me64 = magic64; 34261.54Skamil break; 34271.54Skamil default: 34281.54Skamil break; 34291.54Skamil } 34301.54Skamil break; 34311.54Skamil default: 34321.54Skamil break; 34331.54Skamil } 34341.54Skamil default: 34351.54Skamil break; 34361.54Skamil } 34371.54Skamil 34381.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 34391.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 34401.1Skamil 34411.54Skamil /* Handle PIOD and PT separately as operation values overlap */ 34421.54Skamil switch (type) { 34431.54Skamil case BYTES_TRANSFER_DATA: 34441.54Skamil switch (operation) { 34451.54Skamil case PT_WRITE_D: 34461.54Skamil case PT_WRITE_I: 34471.54Skamil FORKEE_ASSERT_EQ(lookup_me, magic); 34481.54Skamil break; 34491.54Skamil default: 34501.54Skamil break; 34511.54Skamil } 34521.54Skamil break; 34531.54Skamil case BYTES_TRANSFER_DATAIO: 34541.54Skamil switch (operation) { 34551.54Skamil case PIOD_WRITE_D: 34561.54Skamil case PIOD_WRITE_I: 34571.54Skamil switch (size) { 34581.54Skamil case 8: 34591.54Skamil FORKEE_ASSERT_EQ(lookup_me8, magic8); 34601.54Skamil break; 34611.54Skamil case 16: 34621.54Skamil FORKEE_ASSERT_EQ(lookup_me16, magic16); 34631.54Skamil break; 34641.54Skamil case 32: 34651.54Skamil FORKEE_ASSERT_EQ(lookup_me32, magic32); 34661.54Skamil break; 34671.54Skamil case 64: 34681.54Skamil FORKEE_ASSERT_EQ(lookup_me64, magic64); 34691.54Skamil break; 34701.54Skamil default: 34711.54Skamil break; 34721.54Skamil } 34731.54Skamil break; 34741.54Skamil default: 34751.54Skamil break; 34761.54Skamil } 34771.54Skamil break; 34781.54Skamil case BYTES_TRANSFER_TEXT: 34791.54Skamil FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy, 34801.54Skamil sizeof(magic)) == 0); 34811.54Skamil break; 34821.54Skamil case BYTES_TRANSFER_TEXTIO: 34831.54Skamil switch (size) { 34841.54Skamil case 8: 34851.54Skamil FORKEE_ASSERT(memcmp(&magic8, 34861.54Skamil bytes_transfer_dummy, 34871.54Skamil sizeof(magic8)) == 0); 34881.54Skamil break; 34891.54Skamil case 16: 34901.54Skamil FORKEE_ASSERT(memcmp(&magic16, 34911.54Skamil bytes_transfer_dummy, 34921.54Skamil sizeof(magic16)) == 0); 34931.54Skamil break; 34941.54Skamil case 32: 34951.54Skamil FORKEE_ASSERT(memcmp(&magic32, 34961.54Skamil bytes_transfer_dummy, 34971.54Skamil sizeof(magic32)) == 0); 34981.54Skamil break; 34991.54Skamil case 64: 35001.54Skamil FORKEE_ASSERT(memcmp(&magic64, 35011.54Skamil bytes_transfer_dummy, 35021.54Skamil sizeof(magic64)) == 0); 35031.54Skamil break; 35041.54Skamil } 35051.54Skamil break; 35061.54Skamil default: 35071.54Skamil break; 35081.54Skamil } 35091.54Skamil 35101.13Schristos DPRINTF("Before exiting of the child process\n"); 35111.1Skamil _exit(exitval); 35121.1Skamil } 35131.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 35141.1Skamil 35151.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 35161.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 35171.1Skamil 35181.1Skamil validate_status_stopped(status, sigval); 35191.1Skamil 35201.54Skamil /* Check PaX MPROTECT */ 35211.54Skamil if (!can_we_write_to_text(child)) { 35221.54Skamil switch (type) { 35231.54Skamil case BYTES_TRANSFER_TEXTIO: 35241.54Skamil switch (operation) { 35251.54Skamil case PIOD_WRITE_D: 35261.54Skamil case PIOD_WRITE_I: 35271.54Skamil skip = true; 35281.54Skamil break; 35291.54Skamil default: 35301.54Skamil break; 35311.54Skamil } 35321.54Skamil break; 35331.54Skamil case BYTES_TRANSFER_TEXT: 35341.54Skamil switch (operation) { 35351.54Skamil case PT_WRITE_D: 35361.54Skamil case PT_WRITE_I: 35371.54Skamil skip = true; 35381.54Skamil break; 35391.54Skamil default: 35401.54Skamil break; 35411.54Skamil } 35421.54Skamil break; 35431.54Skamil default: 35441.54Skamil break; 35451.54Skamil } 35461.54Skamil } 35471.1Skamil 35481.54Skamil /* Bailout cleanly killing the child process */ 35491.54Skamil if (skip) { 35501.54Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1); 35511.54Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 35521.54Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 35531.54Skamil child); 35541.1Skamil 35551.54Skamil validate_status_signaled(status, SIGKILL, 0); 35561.1Skamil 35571.54Skamil atf_tc_skip("PaX MPROTECT setup prevents writes to .text"); 35581.54Skamil } 35591.1Skamil 35601.54Skamil DPRINTF("Calling operation to transfer bytes between child=%d and " 35611.54Skamil "parent=%d\n", child, getpid()); 35621.1Skamil 35631.54Skamil switch (type) { 35641.54Skamil case BYTES_TRANSFER_TEXTIO: 35651.54Skamil case BYTES_TRANSFER_DATAIO: 35661.54Skamil case BYTES_TRANSFER_AUXV: 35671.54Skamil switch (operation) { 35681.54Skamil case PIOD_WRITE_D: 35691.54Skamil case PIOD_WRITE_I: 35701.54Skamil switch (size) { 35711.54Skamil case 8: 35721.54Skamil lookup_me8 = magic8; 35731.54Skamil break; 35741.54Skamil case 16: 35751.54Skamil lookup_me16 = magic16; 35761.54Skamil break; 35771.54Skamil case 32: 35781.54Skamil lookup_me32 = magic32; 35791.54Skamil break; 35801.54Skamil case 64: 35811.54Skamil lookup_me64 = magic64; 35821.54Skamil break; 35831.54Skamil default: 35841.54Skamil break; 35851.54Skamil } 35861.54Skamil break; 35871.54Skamil default: 35881.54Skamil break; 35891.54Skamil } 35901.54Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); 35911.54Skamil switch (operation) { 35921.54Skamil case PIOD_READ_D: 35931.54Skamil case PIOD_READ_I: 35941.54Skamil switch (size) { 35951.54Skamil case 8: 35961.54Skamil ATF_REQUIRE_EQ(lookup_me8, magic8); 35971.54Skamil break; 35981.54Skamil case 16: 35991.54Skamil ATF_REQUIRE_EQ(lookup_me16, magic16); 36001.54Skamil break; 36011.54Skamil case 32: 36021.54Skamil ATF_REQUIRE_EQ(lookup_me32, magic32); 36031.54Skamil break; 36041.54Skamil case 64: 36051.54Skamil ATF_REQUIRE_EQ(lookup_me64, magic64); 36061.54Skamil break; 36071.54Skamil default: 36081.54Skamil break; 36091.54Skamil } 36101.54Skamil break; 36111.54Skamil case PIOD_READ_AUXV: 36121.54Skamil DPRINTF("Asserting that AUXV length (%zu) is > 0\n", 36131.54Skamil io.piod_len); 36141.54Skamil ATF_REQUIRE(io.piod_len > 0); 36151.54Skamil for (aip = ai; aip->a_type != AT_NULL; aip++) 36161.54Skamil DPRINTF("a_type=%#llx a_v=%#llx\n", 36171.54Skamil (long long int)aip->a_type, 36181.54Skamil (long long int)aip->a_v); 36191.54Skamil break; 36201.54Skamil default: 36211.54Skamil break; 36221.54Skamil } 36231.54Skamil break; 36241.54Skamil case BYTES_TRANSFER_TEXT: 36251.54Skamil switch (operation) { 36261.54Skamil case PT_READ_D: 36271.54Skamil case PT_READ_I: 36281.54Skamil errno = 0; 36291.54Skamil lookup_me = ptrace(operation, child, 36301.54Skamil bytes_transfer_dummy, 0); 36311.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 36321.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 36331.54Skamil break; 36341.54Skamil case PT_WRITE_D: 36351.54Skamil case PT_WRITE_I: 36361.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, 36371.54Skamil bytes_transfer_dummy, magic) 36381.54Skamil != -1); 36391.54Skamil break; 36401.54Skamil default: 36411.54Skamil break; 36421.54Skamil } 36431.54Skamil break; 36441.54Skamil case BYTES_TRANSFER_DATA: 36451.54Skamil switch (operation) { 36461.54Skamil case PT_READ_D: 36471.54Skamil case PT_READ_I: 36481.54Skamil errno = 0; 36491.54Skamil lookup_me = ptrace(operation, child, &lookup_me, 0); 36501.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 36511.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 36521.54Skamil break; 36531.54Skamil case PT_WRITE_D: 36541.54Skamil case PT_WRITE_I: 36551.54Skamil lookup_me = magic; 36561.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me, 36571.54Skamil magic) != -1); 36581.54Skamil break; 36591.54Skamil default: 36601.54Skamil break; 36611.54Skamil } 36621.54Skamil break; 36631.54Skamil default: 36641.54Skamil break; 36651.54Skamil } 36661.1Skamil 36671.13Schristos DPRINTF("Before resuming the child process where it left off and " 36681.1Skamil "without signal to be sent\n"); 36691.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 36701.1Skamil 36711.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 36721.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 36731.1Skamil 36741.1Skamil validate_status_exited(status, exitval); 36751.1Skamil 36761.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 36771.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 36781.1Skamil} 36791.1Skamil 36801.61Skre#define BYTES_TRANSFER(test, operation, size, type) \ 36811.61SkreATF_TC(test); \ 36821.61SkreATF_TC_HEAD(test, tc) \ 36831.61Skre{ \ 36841.61Skre atf_tc_set_md_var(tc, "descr", \ 36851.61Skre "Verify bytes transfer operation" #operation " and size " #size \ 36861.61Skre " of type " #type); \ 36871.61Skre} \ 36881.61Skre \ 36891.61SkreATF_TC_BODY(test, tc) \ 36901.61Skre{ \ 36911.61Skre \ 36921.61Skre bytes_transfer(operation, size, BYTES_TRANSFER_##type); \ 36931.1Skamil} 36941.1Skamil 36951.54Skamil// DATA 36961.1Skamil 36971.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO) 36981.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO) 36991.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO) 37001.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO) 37011.54Skamil 37021.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO) 37031.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO) 37041.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO) 37051.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO) 37061.54Skamil 37071.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO) 37081.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO) 37091.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO) 37101.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO) 37111.54Skamil 37121.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO) 37131.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO) 37141.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO) 37151.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO) 37161.54Skamil 37171.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA) 37181.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA) 37191.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA) 37201.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA) 37211.54Skamil 37221.54Skamil// TEXT 37231.54Skamil 37241.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO) 37251.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO) 37261.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO) 37271.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO) 37281.54Skamil 37291.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO) 37301.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO) 37311.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO) 37321.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO) 37331.54Skamil 37341.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO) 37351.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO) 37361.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO) 37371.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO) 37381.54Skamil 37391.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO) 37401.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO) 37411.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO) 37421.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO) 37431.54Skamil 37441.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT) 37451.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT) 37461.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT) 37471.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT) 37481.1Skamil 37491.54Skamil// AUXV 37501.1Skamil 37511.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV) 37521.1Skamil 37531.54Skamil/// ---------------------------------------------------------------------------- 37541.1Skamil 37551.101Skamilstatic void 37561.101Skamilbytes_transfer_alignment(const char *operation) 37571.101Skamil{ 37581.101Skamil const int exitval = 5; 37591.101Skamil const int sigval = SIGSTOP; 37601.101Skamil pid_t child, wpid; 37611.101Skamil#if defined(TWAIT_HAVE_STATUS) 37621.101Skamil int status; 37631.101Skamil#endif 37641.101Skamil char *buffer; 37651.101Skamil int vector; 37661.101Skamil size_t len; 37671.101Skamil size_t i; 37681.101Skamil int op; 37691.101Skamil 37701.101Skamil struct ptrace_io_desc io; 37711.101Skamil struct ptrace_siginfo info; 37721.101Skamil 37731.101Skamil memset(&io, 0, sizeof(io)); 37741.101Skamil memset(&info, 0, sizeof(info)); 37751.101Skamil 37761.101Skamil /* Testing misaligned byte transfer crossing page boundaries */ 37771.101Skamil len = sysconf(_SC_PAGESIZE) * 2; 37781.101Skamil buffer = malloc(len); 37791.101Skamil ATF_REQUIRE(buffer != NULL); 37801.101Skamil 37811.101Skamil /* Initialize the buffer with random data */ 37821.101Skamil for (i = 0; i < len; i++) 37831.101Skamil buffer[i] = i & 0xff; 37841.101Skamil 37851.101Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 37861.101Skamil SYSCALL_REQUIRE((child = fork()) != -1); 37871.101Skamil if (child == 0) { 37881.101Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 37891.101Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 37901.101Skamil 37911.101Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 37921.101Skamil FORKEE_ASSERT(raise(sigval) == 0); 37931.101Skamil 37941.101Skamil DPRINTF("Before exiting of the child process\n"); 37951.101Skamil _exit(exitval); 37961.101Skamil } 37971.101Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 37981.101Skamil 37991.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38001.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 38011.101Skamil 38021.101Skamil validate_status_stopped(status, sigval); 38031.101Skamil 38041.101Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 38051.101Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 38061.101Skamil != -1); 38071.101Skamil 38081.101Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 38091.101Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 38101.101Skamil "si_errno=%#x\n", 38111.101Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 38121.101Skamil info.psi_siginfo.si_errno); 38131.101Skamil 38141.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 38151.101Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 38161.101Skamil 38171.101Skamil if (strcmp(operation, "PT_READ_I") == 0 || 38181.101Skamil strcmp(operation, "PT_READ_D") == 0) { 38191.101Skamil if (strcmp(operation, "PT_READ_I")) 38201.101Skamil op = PT_READ_I; 38211.101Skamil else 38221.101Skamil op = PT_READ_D; 38231.101Skamil 38241.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 38251.101Skamil errno = 0; 38261.101Skamil vector = ptrace(op, child, buffer + i, 0); 38271.101Skamil ATF_REQUIRE_EQ(errno, 0); 38281.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 38291.101Skamil } 38301.101Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 38311.101Skamil strcmp(operation, "PT_WRITE_D") == 0) { 38321.101Skamil if (strcmp(operation, "PT_WRITE_I")) 38331.101Skamil op = PT_WRITE_I; 38341.101Skamil else 38351.101Skamil op = PT_WRITE_D; 38361.101Skamil 38371.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 38381.101Skamil memcpy(&vector, buffer + i, sizeof(int)); 38391.101Skamil SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector) 38401.101Skamil != -1); 38411.101Skamil } 38421.101Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 38431.101Skamil strcmp(operation, "PIOD_READ_D") == 0) { 38441.101Skamil if (strcmp(operation, "PIOD_READ_I")) 38451.101Skamil op = PIOD_READ_I; 38461.101Skamil else 38471.101Skamil op = PIOD_READ_D; 38481.101Skamil 38491.101Skamil io.piod_op = op; 38501.101Skamil io.piod_addr = &vector; 38511.101Skamil io.piod_len = sizeof(int); 38521.101Skamil 38531.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 38541.101Skamil io.piod_offs = buffer + i; 38551.101Skamil 38561.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 38571.101Skamil != -1); 38581.101Skamil ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int))); 38591.101Skamil } 38601.101Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 38611.101Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 38621.101Skamil if (strcmp(operation, "PIOD_WRITE_I")) 38631.101Skamil op = PIOD_WRITE_I; 38641.101Skamil else 38651.101Skamil op = PIOD_WRITE_D; 38661.101Skamil 38671.101Skamil io.piod_op = op; 38681.101Skamil io.piod_addr = &vector; 38691.101Skamil io.piod_len = sizeof(int); 38701.101Skamil 38711.101Skamil for (i = 0; i <= (len - sizeof(int)); i++) { 38721.101Skamil io.piod_offs = buffer + i; 38731.101Skamil 38741.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 38751.101Skamil != -1); 38761.101Skamil } 38771.101Skamil } else if (strcmp(operation, "PIOD_READ_AUXV") == 0) { 38781.101Skamil io.piod_op = PIOD_READ_AUXV; 38791.101Skamil io.piod_addr = &vector; 38801.101Skamil io.piod_len = sizeof(int); 38811.101Skamil 38821.101Skamil errno = 0; 38831.101Skamil i = 0; 38841.101Skamil /* Read the whole AUXV vector, it has no clear length */ 38851.101Skamil while (errno != EIO) { 38861.101Skamil io.piod_offs = (void *)(intptr_t)i; 38871.101Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) 38881.101Skamil != -1 || (errno == EIO && i > 0)); 38891.101Skamil ++i; 38901.101Skamil } 38911.101Skamil } 38921.101Skamil 38931.101Skamil DPRINTF("Before resuming the child process where it left off " 38941.101Skamil "and without signal to be sent\n"); 38951.101Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 38961.101Skamil 38971.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38981.101Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 38991.101Skamil child); 39001.101Skamil 39011.101Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39021.101Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 39031.101Skamil} 39041.101Skamil 39051.101Skamil#define BYTES_TRANSFER_ALIGNMENT(test, operation) \ 39061.101SkamilATF_TC(test); \ 39071.101SkamilATF_TC_HEAD(test, tc) \ 39081.101Skamil{ \ 39091.101Skamil atf_tc_set_md_var(tc, "descr", \ 39101.101Skamil "Verify bytes transfer for potentially misaligned " \ 39111.101Skamil "operation " operation); \ 39121.101Skamil} \ 39131.101Skamil \ 39141.101SkamilATF_TC_BODY(test, tc) \ 39151.101Skamil{ \ 39161.101Skamil \ 39171.101Skamil bytes_transfer_alignment(operation); \ 39181.101Skamil} 39191.101Skamil 39201.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I") 39211.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D") 39221.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I") 39231.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D") 39241.101Skamil 39251.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I") 39261.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D") 39271.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I") 39281.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D") 39291.101Skamil 39301.101SkamilBYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV") 39311.101Skamil 39321.101Skamil/// ---------------------------------------------------------------------------- 39331.101Skamil 39341.115Skamilstatic void 39351.115Skamilbytes_transfer_eof(const char *operation) 39361.115Skamil{ 39371.115Skamil const int exitval = 5; 39381.115Skamil const int sigval = SIGSTOP; 39391.115Skamil pid_t child, wpid; 39401.115Skamil#if defined(TWAIT_HAVE_STATUS) 39411.115Skamil int status; 39421.115Skamil#endif 39431.115Skamil FILE *fp; 39441.115Skamil char *p; 39451.115Skamil int vector; 39461.115Skamil int op; 39471.115Skamil 39481.115Skamil struct ptrace_io_desc io; 39491.115Skamil struct ptrace_siginfo info; 39501.115Skamil 39511.115Skamil memset(&io, 0, sizeof(io)); 39521.115Skamil memset(&info, 0, sizeof(info)); 39531.115Skamil 39541.115Skamil vector = 0; 39551.115Skamil 39561.115Skamil fp = tmpfile(); 39571.115Skamil ATF_REQUIRE(fp != NULL); 39581.115Skamil 39591.115Skamil p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0); 39601.115Skamil ATF_REQUIRE(p != MAP_FAILED); 39611.115Skamil 39621.115Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 39631.115Skamil SYSCALL_REQUIRE((child = fork()) != -1); 39641.115Skamil if (child == 0) { 39651.115Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 39661.115Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 39671.115Skamil 39681.115Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 39691.115Skamil FORKEE_ASSERT(raise(sigval) == 0); 39701.115Skamil 39711.115Skamil DPRINTF("Before exiting of the child process\n"); 39721.115Skamil _exit(exitval); 39731.115Skamil } 39741.115Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 39751.115Skamil 39761.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39771.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 39781.115Skamil 39791.115Skamil validate_status_stopped(status, sigval); 39801.115Skamil 39811.115Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 39821.115Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) 39831.115Skamil != -1); 39841.115Skamil 39851.115Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 39861.115Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 39871.115Skamil "si_errno=%#x\n", 39881.115Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 39891.115Skamil info.psi_siginfo.si_errno); 39901.115Skamil 39911.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 39921.115Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 39931.115Skamil 39941.115Skamil if (strcmp(operation, "PT_READ_I") == 0 || 39951.115Skamil strcmp(operation, "PT_READ_D") == 0) { 39961.115Skamil if (strcmp(operation, "PT_READ_I")) 39971.115Skamil op = PT_READ_I; 39981.115Skamil else 39991.115Skamil op = PT_READ_D; 40001.115Skamil 40011.115Skamil errno = 0; 40021.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, 0) == -1); 40031.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 40041.115Skamil } else if (strcmp(operation, "PT_WRITE_I") == 0 || 40051.115Skamil strcmp(operation, "PT_WRITE_D") == 0) { 40061.115Skamil if (strcmp(operation, "PT_WRITE_I")) 40071.115Skamil op = PT_WRITE_I; 40081.115Skamil else 40091.115Skamil op = PT_WRITE_D; 40101.115Skamil 40111.115Skamil errno = 0; 40121.115Skamil SYSCALL_REQUIRE(ptrace(op, child, p, vector) == -1); 40131.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 40141.115Skamil } else if (strcmp(operation, "PIOD_READ_I") == 0 || 40151.115Skamil strcmp(operation, "PIOD_READ_D") == 0) { 40161.115Skamil if (strcmp(operation, "PIOD_READ_I")) 40171.115Skamil op = PIOD_READ_I; 40181.115Skamil else 40191.115Skamil op = PIOD_READ_D; 40201.115Skamil 40211.115Skamil io.piod_op = op; 40221.115Skamil io.piod_addr = &vector; 40231.115Skamil io.piod_len = sizeof(int); 40241.115Skamil io.piod_offs = p; 40251.115Skamil 40261.115Skamil errno = 0; 40271.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 40281.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 40291.115Skamil } else if (strcmp(operation, "PIOD_WRITE_I") == 0 || 40301.115Skamil strcmp(operation, "PIOD_WRITE_D") == 0) { 40311.115Skamil if (strcmp(operation, "PIOD_WRITE_I")) 40321.115Skamil op = PIOD_WRITE_I; 40331.115Skamil else 40341.115Skamil op = PIOD_WRITE_D; 40351.115Skamil 40361.115Skamil io.piod_op = op; 40371.115Skamil io.piod_addr = &vector; 40381.115Skamil io.piod_len = sizeof(int); 40391.115Skamil io.piod_offs = p; 40401.115Skamil 40411.115Skamil errno = 0; 40421.115Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1); 40431.115Skamil ATF_REQUIRE_EQ(errno, EINVAL); 40441.115Skamil } 40451.115Skamil 40461.115Skamil DPRINTF("Before resuming the child process where it left off " 40471.115Skamil "and without signal to be sent\n"); 40481.115Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 40491.115Skamil 40501.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 40511.115Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 40521.115Skamil child); 40531.115Skamil 40541.115Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 40551.115Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 40561.115Skamil} 40571.115Skamil 40581.115Skamil#define BYTES_TRANSFER_EOF(test, operation) \ 40591.115SkamilATF_TC(test); \ 40601.115SkamilATF_TC_HEAD(test, tc) \ 40611.115Skamil{ \ 40621.115Skamil atf_tc_set_md_var(tc, "descr", \ 40631.115Skamil "Verify bytes EOF byte transfer for the " operation \ 40641.115Skamil " operation"); \ 40651.115Skamil} \ 40661.115Skamil \ 40671.115SkamilATF_TC_BODY(test, tc) \ 40681.115Skamil{ \ 40691.115Skamil \ 40701.115Skamil bytes_transfer_eof(operation); \ 40711.115Skamil} 40721.115Skamil 40731.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_i, "PT_READ_I") 40741.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_d, "PT_READ_D") 40751.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_i, "PT_WRITE_I") 40761.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_d, "PT_WRITE_D") 40771.115Skamil 40781.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_i, "PIOD_READ_I") 40791.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_d, "PIOD_READ_D") 40801.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_i, "PIOD_WRITE_I") 40811.115SkamilBYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_d, "PIOD_WRITE_D") 40821.115Skamil 40831.115Skamil/// ---------------------------------------------------------------------------- 40841.115Skamil 40851.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS) 40861.72Skamilstatic void 40871.72Skamilaccess_regs(const char *regset, const char *aux) 40881.1Skamil{ 40891.1Skamil const int exitval = 5; 40901.1Skamil const int sigval = SIGSTOP; 40911.1Skamil pid_t child, wpid; 40921.1Skamil#if defined(TWAIT_HAVE_STATUS) 40931.1Skamil int status; 40941.1Skamil#endif 40951.72Skamil#if defined(HAVE_GPREGS) 40961.72Skamil struct reg gpr; 40971.76Sscole register_t rgstr; 40981.1Skamil#endif 40991.72Skamil#if defined(HAVE_FPREGS) 41001.72Skamil struct fpreg fpr; 41011.1Skamil#endif 41021.76Sscole 41031.72Skamil#if !defined(HAVE_GPREGS) 41041.72Skamil if (strcmp(regset, "regs") == 0) 41051.72Skamil atf_tc_fail("Impossible test scenario!"); 41061.1Skamil#endif 41071.1Skamil 41081.72Skamil#if !defined(HAVE_FPREGS) 41091.72Skamil if (strcmp(regset, "fpregs") == 0) 41101.72Skamil atf_tc_fail("Impossible test scenario!"); 41111.1Skamil#endif 41121.1Skamil 41131.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 41141.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 41151.1Skamil if (child == 0) { 41161.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 41171.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 41181.1Skamil 41191.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 41201.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 41211.1Skamil 41221.13Schristos DPRINTF("Before exiting of the child process\n"); 41231.1Skamil _exit(exitval); 41241.1Skamil } 41251.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 41261.1Skamil 41271.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41281.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 41291.1Skamil 41301.1Skamil validate_status_stopped(status, sigval); 41311.1Skamil 41321.1Skamil#if defined(HAVE_GPREGS) 41331.72Skamil if (strcmp(regset, "regs") == 0) { 41341.72Skamil DPRINTF("Call GETREGS for the child process\n"); 41351.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1); 41361.72Skamil 41371.72Skamil if (strcmp(aux, "none") == 0) { 41381.72Skamil DPRINTF("Retrieved registers\n"); 41391.72Skamil } else if (strcmp(aux, "pc") == 0) { 41401.72Skamil rgstr = PTRACE_REG_PC(&gpr); 41411.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 41421.72Skamil } else if (strcmp(aux, "set_pc") == 0) { 41431.72Skamil rgstr = PTRACE_REG_PC(&gpr); 41441.72Skamil PTRACE_REG_SET_PC(&gpr, rgstr); 41451.72Skamil } else if (strcmp(aux, "sp") == 0) { 41461.72Skamil rgstr = PTRACE_REG_SP(&gpr); 41471.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 41481.72Skamil } else if (strcmp(aux, "intrv") == 0) { 41491.72Skamil rgstr = PTRACE_REG_INTRV(&gpr); 41501.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 41511.72Skamil } else if (strcmp(aux, "setregs") == 0) { 41521.72Skamil DPRINTF("Call SETREGS for the child process\n"); 41531.72Skamil SYSCALL_REQUIRE( 41541.72Skamil ptrace(PT_GETREGS, child, &gpr, 0) != -1); 41551.72Skamil } 41561.72Skamil } 41571.1Skamil#endif 41581.1Skamil 41591.72Skamil#if defined(HAVE_FPREGS) 41601.72Skamil if (strcmp(regset, "fpregs") == 0) { 41611.72Skamil DPRINTF("Call GETFPREGS for the child process\n"); 41621.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1); 41631.72Skamil 41641.72Skamil if (strcmp(aux, "getfpregs") == 0) { 41651.72Skamil DPRINTF("Retrieved FP registers\n"); 41661.72Skamil } else if (strcmp(aux, "setfpregs") == 0) { 41671.72Skamil DPRINTF("Call SETFPREGS for the child\n"); 41681.72Skamil SYSCALL_REQUIRE( 41691.72Skamil ptrace(PT_SETFPREGS, child, &fpr, 0) != -1); 41701.72Skamil } 41711.1Skamil } 41721.1Skamil#endif 41731.1Skamil 41741.13Schristos DPRINTF("Before resuming the child process where it left off and " 41751.1Skamil "without signal to be sent\n"); 41761.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 41771.1Skamil 41781.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41791.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 41801.1Skamil 41811.1Skamil validate_status_exited(status, exitval); 41821.1Skamil 41831.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41841.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 41851.1Skamil} 41861.1Skamil 41871.72Skamil#define ACCESS_REGS(test, regset, aux) \ 41881.72SkamilATF_TC(test); \ 41891.72SkamilATF_TC_HEAD(test, tc) \ 41901.72Skamil{ \ 41911.72Skamil atf_tc_set_md_var(tc, "descr", \ 41921.72Skamil "Verify " regset " with auxiliary operation: " aux); \ 41931.72Skamil} \ 41941.72Skamil \ 41951.72SkamilATF_TC_BODY(test, tc) \ 41961.72Skamil{ \ 41971.72Skamil \ 41981.72Skamil access_regs(regset, aux); \ 41991.1Skamil} 42001.1Skamil#endif 42011.1Skamil 42021.72Skamil#if defined(HAVE_GPREGS) 42031.72SkamilACCESS_REGS(access_regs1, "regs", "none") 42041.72SkamilACCESS_REGS(access_regs2, "regs", "pc") 42051.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc") 42061.72SkamilACCESS_REGS(access_regs4, "regs", "sp") 42071.72SkamilACCESS_REGS(access_regs5, "regs", "intrv") 42081.72SkamilACCESS_REGS(access_regs6, "regs", "setregs") 42091.1Skamil#endif 42101.1Skamil#if defined(HAVE_FPREGS) 42111.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs") 42121.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs") 42131.1Skamil#endif 42141.1Skamil 42151.72Skamil/// ---------------------------------------------------------------------------- 42161.1Skamil 42171.1Skamil#if defined(PT_STEP) 42181.1Skamilstatic void 42191.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored) 42201.1Skamil{ 42211.1Skamil const int exitval = 5; 42221.1Skamil const int sigval = SIGSTOP; 42231.1Skamil pid_t child, wpid; 42241.1Skamil#if defined(TWAIT_HAVE_STATUS) 42251.1Skamil int status; 42261.1Skamil#endif 42271.1Skamil int happy; 42281.95Skamil struct sigaction sa; 42291.81Skamil struct ptrace_siginfo info; 42301.95Skamil sigset_t intmask; 42311.95Skamil struct kinfo_proc2 kp; 42321.95Skamil size_t len = sizeof(kp); 42331.95Skamil 42341.95Skamil int name[6]; 42351.95Skamil const size_t namelen = __arraycount(name); 42361.95Skamil ki_sigset_t kp_sigmask; 42371.95Skamil ki_sigset_t kp_sigignore; 42381.1Skamil 42391.1Skamil#if defined(__arm__) 42401.1Skamil /* PT_STEP not supported on arm 32-bit */ 42411.1Skamil atf_tc_expect_fail("PR kern/52119"); 42421.1Skamil#endif 42431.1Skamil 42441.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 42451.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 42461.1Skamil if (child == 0) { 42471.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 42481.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 42491.1Skamil 42501.95Skamil if (masked) { 42511.95Skamil sigemptyset(&intmask); 42521.95Skamil sigaddset(&intmask, SIGTRAP); 42531.95Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 42541.95Skamil } 42551.95Skamil 42561.95Skamil if (ignored) { 42571.95Skamil memset(&sa, 0, sizeof(sa)); 42581.95Skamil sa.sa_handler = SIG_IGN; 42591.95Skamil sigemptyset(&sa.sa_mask); 42601.95Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 42611.95Skamil } 42621.95Skamil 42631.1Skamil happy = check_happy(999); 42641.1Skamil 42651.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 42661.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 42671.1Skamil 42681.1Skamil FORKEE_ASSERT_EQ(happy, check_happy(999)); 42691.1Skamil 42701.13Schristos DPRINTF("Before exiting of the child process\n"); 42711.1Skamil _exit(exitval); 42721.1Skamil } 42731.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 42741.1Skamil 42751.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 42761.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 42771.1Skamil 42781.1Skamil validate_status_stopped(status, sigval); 42791.1Skamil 42801.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 42811.81Skamil SYSCALL_REQUIRE( 42821.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 42831.81Skamil 42841.81Skamil DPRINTF("Before checking siginfo_t\n"); 42851.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 42861.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 42871.81Skamil 42881.95Skamil name[0] = CTL_KERN, 42891.95Skamil name[1] = KERN_PROC2, 42901.95Skamil name[2] = KERN_PROC_PID; 42911.95Skamil name[3] = child; 42921.95Skamil name[4] = sizeof(kp); 42931.95Skamil name[5] = 1; 42941.95Skamil 42951.95Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 42961.95Skamil 42971.95Skamil if (masked) 42981.95Skamil kp_sigmask = kp.p_sigmask; 42991.95Skamil 43001.95Skamil if (ignored) 43011.95Skamil kp_sigignore = kp.p_sigignore; 43021.95Skamil 43031.1Skamil while (N --> 0) { 43041.2Skamil if (setstep) { 43051.13Schristos DPRINTF("Before resuming the child process where it " 43061.2Skamil "left off and without signal to be sent (use " 43071.9Skamil "PT_SETSTEP and PT_CONTINUE)\n"); 43081.13Schristos SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1); 43091.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) 43101.2Skamil != -1); 43111.2Skamil } else { 43121.13Schristos DPRINTF("Before resuming the child process where it " 43131.2Skamil "left off and without signal to be sent (use " 43141.2Skamil "PT_STEP)\n"); 43151.13Schristos SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) 43161.2Skamil != -1); 43171.2Skamil } 43181.1Skamil 43191.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43201.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 43211.1Skamil child); 43221.1Skamil 43231.1Skamil validate_status_stopped(status, SIGTRAP); 43241.2Skamil 43251.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 43261.81Skamil SYSCALL_REQUIRE( 43271.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 43281.81Skamil 43291.81Skamil DPRINTF("Before checking siginfo_t\n"); 43301.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 43311.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE); 43321.81Skamil 43331.2Skamil if (setstep) { 43341.13Schristos SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1); 43351.2Skamil } 43361.95Skamil 43371.95Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 43381.95Skamil 43391.95Skamil if (masked) { 43401.95Skamil DPRINTF("kp_sigmask=" 43411.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 43421.95Skamil PRIx32 "\n", 43431.95Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 43441.95Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 43451.95Skamil 43461.95Skamil DPRINTF("kp.p_sigmask=" 43471.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 43481.95Skamil PRIx32 "\n", 43491.95Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 43501.95Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 43511.95Skamil 43521.95Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 43531.95Skamil sizeof(kp_sigmask))); 43541.95Skamil } 43551.95Skamil 43561.95Skamil if (ignored) { 43571.95Skamil DPRINTF("kp_sigignore=" 43581.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 43591.95Skamil PRIx32 "\n", 43601.95Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 43611.95Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 43621.95Skamil 43631.95Skamil DPRINTF("kp.p_sigignore=" 43641.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 43651.95Skamil PRIx32 "\n", 43661.95Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 43671.95Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 43681.95Skamil 43691.95Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 43701.95Skamil sizeof(kp_sigignore))); 43711.95Skamil } 43721.1Skamil } 43731.1Skamil 43741.13Schristos DPRINTF("Before resuming the child process where it left off and " 43751.1Skamil "without signal to be sent\n"); 43761.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 43771.1Skamil 43781.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43791.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 43801.1Skamil 43811.1Skamil validate_status_exited(status, exitval); 43821.1Skamil 43831.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 43841.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 43851.1Skamil} 43861.1Skamil 43871.73Skamil#define PTRACE_STEP(test, N, setstep) \ 43881.73SkamilATF_TC(test); \ 43891.73SkamilATF_TC_HEAD(test, tc) \ 43901.73Skamil{ \ 43911.73Skamil atf_tc_set_md_var(tc, "descr", \ 43921.74Skamil "Verify " #N " (PT_SETSTEP set to: " #setstep ")"); \ 43931.73Skamil} \ 43941.73Skamil \ 43951.73SkamilATF_TC_BODY(test, tc) \ 43961.73Skamil{ \ 43971.73Skamil \ 43981.95Skamil ptrace_step(N, setstep, false, false); \ 43991.1Skamil} 44001.1Skamil 44011.73SkamilPTRACE_STEP(step1, 1, 0) 44021.73SkamilPTRACE_STEP(step2, 2, 0) 44031.73SkamilPTRACE_STEP(step3, 3, 0) 44041.73SkamilPTRACE_STEP(step4, 4, 0) 44051.73SkamilPTRACE_STEP(setstep1, 1, 1) 44061.73SkamilPTRACE_STEP(setstep2, 2, 1) 44071.73SkamilPTRACE_STEP(setstep3, 3, 1) 44081.73SkamilPTRACE_STEP(setstep4, 4, 1) 44091.95Skamil 44101.95SkamilATF_TC(step_signalmasked); 44111.95SkamilATF_TC_HEAD(step_signalmasked, tc) 44121.95Skamil{ 44131.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP"); 44141.95Skamil} 44151.95Skamil 44161.95SkamilATF_TC_BODY(step_signalmasked, tc) 44171.95Skamil{ 44181.95Skamil 44191.95Skamil ptrace_step(1, 0, true, false); 44201.95Skamil} 44211.95Skamil 44221.95SkamilATF_TC(step_signalignored); 44231.95SkamilATF_TC_HEAD(step_signalignored, tc) 44241.95Skamil{ 44251.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP"); 44261.95Skamil} 44271.95Skamil 44281.95SkamilATF_TC_BODY(step_signalignored, tc) 44291.95Skamil{ 44301.95Skamil 44311.95Skamil ptrace_step(1, 0, false, true); 44321.95Skamil} 44331.1Skamil#endif 44341.1Skamil 44351.73Skamil/// ---------------------------------------------------------------------------- 44361.1Skamil 44371.75Skamilstatic void 44381.75Skamilptrace_kill(const char *type) 44391.1Skamil{ 44401.75Skamil const int sigval = SIGSTOP; 44411.1Skamil pid_t child, wpid; 44421.1Skamil#if defined(TWAIT_HAVE_STATUS) 44431.1Skamil int status; 44441.1Skamil#endif 44451.1Skamil 44461.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 44471.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 44481.1Skamil if (child == 0) { 44491.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 44501.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 44511.1Skamil 44521.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 44531.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 44541.1Skamil 44551.1Skamil /* NOTREACHED */ 44561.1Skamil FORKEE_ASSERTX(0 && 44571.1Skamil "Child should be terminated by a signal from its parent"); 44581.1Skamil } 44591.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 44601.1Skamil 44611.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44621.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44631.1Skamil 44641.1Skamil validate_status_stopped(status, sigval); 44651.1Skamil 44661.75Skamil DPRINTF("Before killing the child process with %s\n", type); 44671.75Skamil if (strcmp(type, "ptrace(PT_KILL)") == 0) { 44681.75Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1); 44691.75Skamil } else if (strcmp(type, "kill(SIGKILL)") == 0) { 44701.75Skamil kill(child, SIGKILL); 44711.75Skamil } else if (strcmp(type, "killpg(SIGKILL)") == 0) { 44721.75Skamil setpgid(child, 0); 44731.75Skamil killpg(getpgid(child), SIGKILL); 44741.75Skamil } 44751.1Skamil 44761.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44771.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44781.1Skamil 44791.75Skamil validate_status_signaled(status, SIGKILL, 0); 44801.1Skamil 44811.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44821.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 44831.1Skamil} 44841.1Skamil 44851.75Skamil#define PTRACE_KILL(test, type) \ 44861.75SkamilATF_TC(test); \ 44871.75SkamilATF_TC_HEAD(test, tc) \ 44881.75Skamil{ \ 44891.75Skamil atf_tc_set_md_var(tc, "descr", \ 44901.75Skamil "Verify killing the child with " type); \ 44911.75Skamil} \ 44921.75Skamil \ 44931.75SkamilATF_TC_BODY(test, tc) \ 44941.75Skamil{ \ 44951.75Skamil \ 44961.75Skamil ptrace_kill(type); \ 44971.1Skamil} 44981.1Skamil 44991.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1 45001.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)") 45011.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)") 45021.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)") 45031.1Skamil 45041.75Skamil/// ---------------------------------------------------------------------------- 45051.1Skamil 45061.77Skamilstatic void 45071.77Skamiltraceme_lwpinfo(const int threads) 45081.1Skamil{ 45091.1Skamil const int sigval = SIGSTOP; 45101.77Skamil const int sigval2 = SIGINT; 45111.1Skamil pid_t child, wpid; 45121.1Skamil#if defined(TWAIT_HAVE_STATUS) 45131.1Skamil int status; 45141.1Skamil#endif 45151.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 45161.77Skamil struct ptrace_siginfo info; 45171.77Skamil 45181.77Skamil /* Maximum number of supported threads in this test */ 45191.77Skamil pthread_t t[3]; 45201.77Skamil int n, rv; 45211.77Skamil 45221.77Skamil ATF_REQUIRE((int)__arraycount(t) >= threads); 45231.1Skamil 45241.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 45251.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 45261.1Skamil if (child == 0) { 45271.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 45281.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 45291.1Skamil 45301.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 45311.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 45321.1Skamil 45331.77Skamil for (n = 0; n < threads; n++) { 45341.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 45351.77Skamil FORKEE_ASSERT(rv == 0); 45361.77Skamil } 45371.77Skamil 45381.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval2)); 45391.77Skamil FORKEE_ASSERT(raise(sigval2) == 0); 45401.77Skamil 45411.77Skamil /* NOTREACHED */ 45421.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 45431.1Skamil } 45441.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 45451.1Skamil 45461.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45471.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 45481.1Skamil 45491.1Skamil validate_status_stopped(status, sigval); 45501.1Skamil 45511.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 45521.77Skamil SYSCALL_REQUIRE( 45531.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 45541.77Skamil 45551.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 45561.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 45571.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 45581.77Skamil info.psi_siginfo.si_errno); 45591.77Skamil 45601.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 45611.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 45621.77Skamil 45631.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 45641.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 45651.1Skamil 45661.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 45671.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 45681.1Skamil 45691.13Schristos DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n", 45701.77Skamil lwp.pl_lwpid); 45711.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 45721.1Skamil 45731.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 45741.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 45751.1Skamil 45761.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 45771.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 45781.1Skamil 45791.13Schristos DPRINTF("Before resuming the child process where it left off and " 45801.1Skamil "without signal to be sent\n"); 45811.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 45821.1Skamil 45831.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45841.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 45851.1Skamil 45861.77Skamil validate_status_stopped(status, sigval2); 45871.77Skamil 45881.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 45891.77Skamil SYSCALL_REQUIRE( 45901.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 45911.77Skamil 45921.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 45931.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 45941.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 45951.77Skamil info.psi_siginfo.si_errno); 45961.77Skamil 45971.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2); 45981.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 45991.77Skamil 46001.77Skamil memset(&lwp, 0, sizeof(lwp)); 46011.77Skamil 46021.77Skamil for (n = 0; n <= threads; n++) { 46031.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 46041.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 46051.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 46061.77Skamil 46071.77Skamil DPRINTF("Assert that the thread exists\n"); 46081.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 46091.77Skamil 46101.77Skamil DPRINTF("Assert that lwp thread %d received expected event\n", 46111.77Skamil lwp.pl_lwpid); 46121.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ? 46131.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 46141.77Skamil } 46151.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 46161.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 46171.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 46181.77Skamil 46191.77Skamil DPRINTF("Assert that there are no more threads\n"); 46201.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 46211.77Skamil 46221.77Skamil DPRINTF("Before resuming the child process where it left off and " 46231.77Skamil "without signal to be sent\n"); 46241.77Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1); 46251.77Skamil 46261.77Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46271.77Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 46281.77Skamil 46291.77Skamil validate_status_signaled(status, SIGKILL, 0); 46301.1Skamil 46311.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46321.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 46331.1Skamil} 46341.1Skamil 46351.77Skamil#define TRACEME_LWPINFO(test, threads) \ 46361.77SkamilATF_TC(test); \ 46371.77SkamilATF_TC_HEAD(test, tc) \ 46381.77Skamil{ \ 46391.77Skamil atf_tc_set_md_var(tc, "descr", \ 46401.77Skamil "Verify LWPINFO with the child with " #threads \ 46411.77Skamil " spawned extra threads"); \ 46421.77Skamil} \ 46431.77Skamil \ 46441.77SkamilATF_TC_BODY(test, tc) \ 46451.77Skamil{ \ 46461.77Skamil \ 46471.77Skamil traceme_lwpinfo(threads); \ 46481.1Skamil} 46491.1Skamil 46501.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0) 46511.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1) 46521.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2) 46531.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3) 46541.77Skamil 46551.77Skamil/// ---------------------------------------------------------------------------- 46561.77Skamil 46571.77Skamil#if defined(TWAIT_HAVE_PID) 46581.77Skamilstatic void 46591.77Skamilattach_lwpinfo(const int threads) 46601.1Skamil{ 46611.77Skamil const int sigval = SIGINT; 46621.1Skamil struct msg_fds parent_tracee, parent_tracer; 46631.1Skamil const int exitval_tracer = 10; 46641.1Skamil pid_t tracee, tracer, wpid; 46651.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 46661.1Skamil#if defined(TWAIT_HAVE_STATUS) 46671.1Skamil int status; 46681.1Skamil#endif 46691.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 46701.77Skamil struct ptrace_siginfo info; 46711.77Skamil 46721.77Skamil /* Maximum number of supported threads in this test */ 46731.77Skamil pthread_t t[3]; 46741.77Skamil int n, rv; 46751.1Skamil 46761.13Schristos DPRINTF("Spawn tracee\n"); 46771.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 46781.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 46791.1Skamil tracee = atf_utils_fork(); 46801.1Skamil if (tracee == 0) { 46811.1Skamil /* Wait for message from the parent */ 46821.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 46831.1Skamil 46841.77Skamil CHILD_FROM_PARENT("spawn threads", parent_tracee, msg); 46851.77Skamil 46861.77Skamil for (n = 0; n < threads; n++) { 46871.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 46881.77Skamil FORKEE_ASSERT(rv == 0); 46891.77Skamil } 46901.77Skamil 46911.77Skamil CHILD_TO_PARENT("tracee exit", parent_tracee, msg); 46921.77Skamil 46931.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 46941.77Skamil FORKEE_ASSERT(raise(sigval) == 0); 46951.77Skamil 46961.77Skamil /* NOTREACHED */ 46971.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 46981.1Skamil } 46991.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 47001.1Skamil 47011.13Schristos DPRINTF("Spawn debugger\n"); 47021.1Skamil tracer = atf_utils_fork(); 47031.1Skamil if (tracer == 0) { 47041.1Skamil /* No IPC to communicate with the child */ 47051.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 47061.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 47071.1Skamil 47081.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 47091.1Skamil FORKEE_REQUIRE_SUCCESS( 47101.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 47111.1Skamil 47121.1Skamil forkee_status_stopped(status, SIGSTOP); 47131.1Skamil 47141.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 47151.77Skamil "tracee"); 47161.77Skamil FORKEE_ASSERT( 47171.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 47181.77Skamil 47191.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 47201.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 47211.77Skamil "si_errno=%#x\n", 47221.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 47231.77Skamil info.psi_siginfo.si_errno); 47241.77Skamil 47251.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 47261.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 47271.77Skamil 47281.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 47291.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 47301.1Skamil != -1); 47311.1Skamil 47321.13Schristos DPRINTF("Assert that there exists a thread\n"); 47331.77Skamil FORKEE_ASSERTX(lwp.pl_lwpid > 0); 47341.1Skamil 47351.13Schristos DPRINTF("Assert that lwp thread %d received event " 47361.77Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 47371.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 47381.1Skamil 47391.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 47401.77Skamil "tracee\n"); 47411.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 47421.1Skamil != -1); 47431.1Skamil 47441.77Skamil DPRINTF("Assert that there are no more lwp threads in " 47451.77Skamil "tracee\n"); 47461.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 47471.1Skamil 47481.1Skamil /* Resume tracee with PT_CONTINUE */ 47491.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 47501.1Skamil 47511.1Skamil /* Inform parent that tracer has attached to tracee */ 47521.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 47531.77Skamil 47541.1Skamil /* Wait for parent */ 47551.1Skamil CHILD_FROM_PARENT("tracer wait", parent_tracer, msg); 47561.1Skamil 47571.77Skamil /* Wait for tracee and assert that it raised a signal */ 47581.77Skamil FORKEE_REQUIRE_SUCCESS( 47591.77Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 47601.77Skamil 47611.77Skamil forkee_status_stopped(status, SIGINT); 47621.77Skamil 47631.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 47641.77Skamil "child"); 47651.77Skamil FORKEE_ASSERT( 47661.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 47671.77Skamil 47681.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 47691.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 47701.77Skamil "si_errno=%#x\n", 47711.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 47721.77Skamil info.psi_siginfo.si_errno); 47731.77Skamil 47741.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 47751.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 47761.77Skamil 47771.77Skamil memset(&lwp, 0, sizeof(lwp)); 47781.77Skamil 47791.77Skamil for (n = 0; n <= threads; n++) { 47801.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 47811.77Skamil "child\n"); 47821.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, 47831.77Skamil sizeof(lwp)) != -1); 47841.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 47851.77Skamil 47861.77Skamil DPRINTF("Assert that the thread exists\n"); 47871.77Skamil FORKEE_ASSERT(lwp.pl_lwpid > 0); 47881.77Skamil 47891.77Skamil DPRINTF("Assert that lwp thread %d received expected " 47901.77Skamil "event\n", lwp.pl_lwpid); 47911.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 47921.77Skamil info.psi_lwpid == lwp.pl_lwpid ? 47931.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 47941.77Skamil } 47951.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 47961.77Skamil "tracee\n"); 47971.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 47981.77Skamil != -1); 47991.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 48001.77Skamil 48011.77Skamil DPRINTF("Assert that there are no more threads\n"); 48021.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 48031.77Skamil 48041.77Skamil DPRINTF("Before resuming the child process where it left off " 48051.77Skamil "and without signal to be sent\n"); 48061.77Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL) 48071.77Skamil != -1); 48081.77Skamil 48091.1Skamil /* Wait for tracee and assert that it exited */ 48101.1Skamil FORKEE_REQUIRE_SUCCESS( 48111.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 48121.1Skamil 48131.77Skamil forkee_status_signaled(status, SIGKILL, 0); 48141.1Skamil 48151.13Schristos DPRINTF("Before exiting of the tracer process\n"); 48161.1Skamil _exit(exitval_tracer); 48171.1Skamil } 48181.1Skamil 48191.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 48201.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 48211.1Skamil 48221.77Skamil DPRINTF("Resume the tracee and spawn threads\n"); 48231.77Skamil PARENT_TO_CHILD("spawn threads", parent_tracee, msg); 48241.77Skamil 48251.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 48261.77Skamil PARENT_FROM_CHILD("tracee exit", parent_tracee, msg); 48271.1Skamil 48281.77Skamil DPRINTF("Resume the tracer and let it detect multiple threads\n"); 48291.1Skamil PARENT_TO_CHILD("tracer wait", parent_tracer, msg); 48301.1Skamil 48311.13Schristos DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n", 48321.1Skamil TWAIT_FNAME); 48331.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 48341.1Skamil tracer); 48351.1Skamil 48361.1Skamil validate_status_exited(status, exitval_tracer); 48371.1Skamil 48381.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 48391.1Skamil TWAIT_FNAME); 48401.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 48411.1Skamil tracee); 48421.1Skamil 48431.77Skamil validate_status_signaled(status, SIGKILL, 0); 48441.1Skamil 48451.1Skamil msg_close(&parent_tracer); 48461.1Skamil msg_close(&parent_tracee); 48471.1Skamil} 48481.77Skamil 48491.77Skamil#define ATTACH_LWPINFO(test, threads) \ 48501.77SkamilATF_TC(test); \ 48511.77SkamilATF_TC_HEAD(test, tc) \ 48521.77Skamil{ \ 48531.77Skamil atf_tc_set_md_var(tc, "descr", \ 48541.77Skamil "Verify LWPINFO with the child with " #threads \ 48551.77Skamil " spawned extra threads (tracer is not the original " \ 48561.77Skamil "parent)"); \ 48571.77Skamil} \ 48581.77Skamil \ 48591.77SkamilATF_TC_BODY(test, tc) \ 48601.77Skamil{ \ 48611.77Skamil \ 48621.77Skamil attach_lwpinfo(threads); \ 48631.77Skamil} 48641.77Skamil 48651.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0) 48661.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1) 48671.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2) 48681.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3) 48691.1Skamil#endif 48701.1Skamil 48711.77Skamil/// ---------------------------------------------------------------------------- 48721.77Skamil 48731.1Skamilstatic void 48741.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught) 48751.1Skamil{ 48761.1Skamil const int exitval = 5; 48771.1Skamil const int sigval = SIGINT; 48781.1Skamil const int sigfaked = SIGTRAP; 48791.1Skamil const int sicodefaked = TRAP_BRKPT; 48801.1Skamil pid_t child, wpid; 48811.1Skamil struct sigaction sa; 48821.1Skamil#if defined(TWAIT_HAVE_STATUS) 48831.1Skamil int status; 48841.1Skamil#endif 48851.1Skamil struct ptrace_siginfo info; 48861.1Skamil memset(&info, 0, sizeof(info)); 48871.1Skamil 48881.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 48891.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 48901.1Skamil if (child == 0) { 48911.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 48921.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 48931.1Skamil 48941.79Skamil sa.sa_sigaction = sah; 48951.1Skamil sa.sa_flags = SA_SIGINFO; 48961.1Skamil sigemptyset(&sa.sa_mask); 48971.1Skamil 48981.79Skamil FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL) 48991.79Skamil != -1); 49001.1Skamil 49011.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 49021.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 49031.1Skamil 49041.79Skamil FORKEE_ASSERT_EQ(*signal_caught, 1); 49051.1Skamil 49061.13Schristos DPRINTF("Before exiting of the child process\n"); 49071.1Skamil _exit(exitval); 49081.1Skamil } 49091.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 49101.1Skamil 49111.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49121.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 49131.1Skamil 49141.1Skamil validate_status_stopped(status, sigval); 49151.1Skamil 49161.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 49171.61Skre SYSCALL_REQUIRE( 49181.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 49191.1Skamil 49201.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 49211.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 49221.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 49231.1Skamil info.psi_siginfo.si_errno); 49241.1Skamil 49251.79Skamil if (faked) { 49261.79Skamil DPRINTF("Before setting new faked signal to signo=%d " 49271.79Skamil "si_code=%d\n", sigfaked, sicodefaked); 49281.79Skamil info.psi_siginfo.si_signo = sigfaked; 49291.79Skamil info.psi_siginfo.si_code = sicodefaked; 49301.79Skamil } 49311.1Skamil 49321.13Schristos DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n"); 49331.61Skre SYSCALL_REQUIRE( 49341.61Skre ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1); 49351.1Skamil 49361.79Skamil if (faked) { 49371.79Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 49381.79Skamil "child\n"); 49391.79Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 49401.79Skamil sizeof(info)) != -1); 49411.1Skamil 49421.79Skamil DPRINTF("Before checking siginfo_t\n"); 49431.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked); 49441.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked); 49451.79Skamil } 49461.1Skamil 49471.13Schristos DPRINTF("Before resuming the child process where it left off and " 49481.1Skamil "without signal to be sent\n"); 49491.79Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 49501.79Skamil faked ? sigfaked : sigval) != -1); 49511.1Skamil 49521.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49531.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 49541.1Skamil 49551.1Skamil validate_status_exited(status, exitval); 49561.1Skamil 49571.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49581.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 49591.1Skamil} 49601.1Skamil 49611.79Skamil#define PTRACE_SIGINFO(test, faked) \ 49621.79SkamilATF_TC(test); \ 49631.79SkamilATF_TC_HEAD(test, tc) \ 49641.79Skamil{ \ 49651.79Skamil atf_tc_set_md_var(tc, "descr", \ 49661.79Skamil "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls" \ 49671.79Skamil "with%s setting signal to new value", faked ? "" : "out"); \ 49681.79Skamil} \ 49691.79Skamil \ 49701.79Skamilstatic int test##_caught = 0; \ 49711.79Skamil \ 49721.79Skamilstatic void \ 49731.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx) \ 49741.79Skamil{ \ 49751.79Skamil if (faked) { \ 49761.79Skamil FORKEE_ASSERT_EQ(sig, SIGTRAP); \ 49771.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP); \ 49781.79Skamil FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT); \ 49791.79Skamil } else { \ 49801.79Skamil FORKEE_ASSERT_EQ(sig, SIGINT); \ 49811.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGINT); \ 49821.79Skamil FORKEE_ASSERT_EQ(info->si_code, SI_LWP); \ 49831.79Skamil } \ 49841.79Skamil \ 49851.79Skamil ++ test##_caught; \ 49861.79Skamil} \ 49871.79Skamil \ 49881.79SkamilATF_TC_BODY(test, tc) \ 49891.79Skamil{ \ 49901.79Skamil \ 49911.79Skamil ptrace_siginfo(faked, test##_sighandler, & test##_caught); \ 49921.79Skamil} 49931.79Skamil 49941.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false) 49951.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true) 49961.79Skamil 49971.79Skamil/// ---------------------------------------------------------------------------- 49981.79Skamil 49991.97Skamilstatic void 50001.97Skamiltraceme_exec(bool masked, bool ignored) 50011.1Skamil{ 50021.1Skamil const int sigval = SIGTRAP; 50031.1Skamil pid_t child, wpid; 50041.1Skamil#if defined(TWAIT_HAVE_STATUS) 50051.1Skamil int status; 50061.1Skamil#endif 50071.97Skamil struct sigaction sa; 50081.97Skamil struct ptrace_siginfo info; 50091.97Skamil sigset_t intmask; 50101.97Skamil struct kinfo_proc2 kp; 50111.97Skamil size_t len = sizeof(kp); 50121.97Skamil 50131.97Skamil int name[6]; 50141.97Skamil const size_t namelen = __arraycount(name); 50151.97Skamil ki_sigset_t kp_sigmask; 50161.97Skamil ki_sigset_t kp_sigignore; 50171.1Skamil 50181.1Skamil memset(&info, 0, sizeof(info)); 50191.1Skamil 50201.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 50211.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 50221.1Skamil if (child == 0) { 50231.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 50241.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 50251.1Skamil 50261.97Skamil if (masked) { 50271.97Skamil sigemptyset(&intmask); 50281.97Skamil sigaddset(&intmask, sigval); 50291.97Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 50301.97Skamil } 50311.97Skamil 50321.97Skamil if (ignored) { 50331.97Skamil memset(&sa, 0, sizeof(sa)); 50341.97Skamil sa.sa_handler = SIG_IGN; 50351.97Skamil sigemptyset(&sa.sa_mask); 50361.97Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 50371.97Skamil } 50381.97Skamil 50391.13Schristos DPRINTF("Before calling execve(2) from child\n"); 50401.1Skamil execlp("/bin/echo", "/bin/echo", NULL); 50411.1Skamil 50421.1Skamil FORKEE_ASSERT(0 && "Not reached"); 50431.1Skamil } 50441.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 50451.1Skamil 50461.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 50471.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 50481.1Skamil 50491.1Skamil validate_status_stopped(status, sigval); 50501.1Skamil 50511.97Skamil name[0] = CTL_KERN, 50521.97Skamil name[1] = KERN_PROC2, 50531.97Skamil name[2] = KERN_PROC_PID; 50541.97Skamil name[3] = getpid(); 50551.97Skamil name[4] = sizeof(kp); 50561.97Skamil name[5] = 1; 50571.97Skamil 50581.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 50591.97Skamil 50601.97Skamil if (masked) 50611.97Skamil kp_sigmask = kp.p_sigmask; 50621.97Skamil 50631.97Skamil if (ignored) 50641.97Skamil kp_sigignore = kp.p_sigignore; 50651.97Skamil 50661.97Skamil name[3] = getpid(); 50671.97Skamil 50681.97Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 50691.97Skamil 50701.97Skamil if (masked) { 50711.97Skamil DPRINTF("kp_sigmask=" 50721.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 50731.97Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 50741.97Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 50751.97Skamil 50761.97Skamil DPRINTF("kp.p_sigmask=" 50771.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 50781.97Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 50791.97Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 50801.97Skamil 50811.97Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 50821.97Skamil sizeof(kp_sigmask))); 50831.97Skamil } 50841.97Skamil 50851.97Skamil if (ignored) { 50861.97Skamil DPRINTF("kp_sigignore=" 50871.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 50881.97Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 50891.97Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 50901.97Skamil 50911.97Skamil DPRINTF("kp.p_sigignore=" 50921.97Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 50931.97Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 50941.97Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 50951.97Skamil 50961.97Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 50971.97Skamil sizeof(kp_sigignore))); 50981.97Skamil } 50991.97Skamil 51001.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 51011.61Skre SYSCALL_REQUIRE( 51021.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 51031.1Skamil 51041.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 51051.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 51061.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 51071.1Skamil info.psi_siginfo.si_errno); 51081.1Skamil 51091.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 51101.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 51111.1Skamil 51121.13Schristos DPRINTF("Before resuming the child process where it left off and " 51131.1Skamil "without signal to be sent\n"); 51141.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 51151.1Skamil 51161.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51171.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 51181.1Skamil 51191.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51201.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 51211.1Skamil} 51221.1Skamil 51231.97Skamil#define TRACEME_EXEC(test, masked, ignored) \ 51241.97SkamilATF_TC(test); \ 51251.97SkamilATF_TC_HEAD(test, tc) \ 51261.97Skamil{ \ 51271.97Skamil atf_tc_set_md_var(tc, "descr", \ 51281.97Skamil "Detect SIGTRAP TRAP_EXEC from " \ 51291.97Skamil "child%s%s", masked ? " with masked signal" : "", \ 51301.97Skamil masked ? " with ignored signal" : ""); \ 51311.97Skamil} \ 51321.97Skamil \ 51331.97SkamilATF_TC_BODY(test, tc) \ 51341.97Skamil{ \ 51351.97Skamil \ 51361.97Skamil traceme_exec(masked, ignored); \ 51371.97Skamil} 51381.97Skamil 51391.97SkamilTRACEME_EXEC(traceme_exec, false, false) 51401.97SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false) 51411.97SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true) 51421.97Skamil 51431.82Skamil/// ---------------------------------------------------------------------------- 51441.82Skamil 51451.83Skamilstatic volatile int done; 51461.1Skamil 51471.83Skamilstatic void * 51481.83Skamiltrace_threads_cb(void *arg __unused) 51491.1Skamil{ 51501.1Skamil 51511.83Skamil done++; 51521.83Skamil 51531.83Skamil while (done < 3) 51541.83Skamil continue; 51551.83Skamil 51561.83Skamil return NULL; 51571.1Skamil} 51581.1Skamil 51591.83Skamilstatic void 51601.83Skamiltrace_threads(bool trace_create, bool trace_exit) 51611.1Skamil{ 51621.1Skamil const int sigval = SIGSTOP; 51631.1Skamil pid_t child, wpid; 51641.1Skamil#if defined(TWAIT_HAVE_STATUS) 51651.1Skamil int status; 51661.1Skamil#endif 51671.1Skamil ptrace_state_t state; 51681.1Skamil const int slen = sizeof(state); 51691.1Skamil ptrace_event_t event; 51701.1Skamil const int elen = sizeof(event); 51711.83Skamil struct ptrace_siginfo info; 51721.83Skamil 51731.83Skamil pthread_t t[3]; 51741.83Skamil int rv; 51751.83Skamil size_t n; 51761.1Skamil lwpid_t lid; 51771.83Skamil 51781.83Skamil /* Track created and exited threads */ 51791.83Skamil bool traced_lwps[__arraycount(t)]; 51801.83Skamil 51811.83Skamil atf_tc_skip("PR kern/51995"); 51821.1Skamil 51831.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 51841.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 51851.1Skamil if (child == 0) { 51861.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 51871.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 51881.1Skamil 51891.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 51901.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 51911.1Skamil 51921.83Skamil for (n = 0; n < __arraycount(t); n++) { 51931.83Skamil rv = pthread_create(&t[n], NULL, trace_threads_cb, 51941.83Skamil NULL); 51951.83Skamil FORKEE_ASSERT(rv == 0); 51961.83Skamil } 51971.1Skamil 51981.83Skamil for (n = 0; n < __arraycount(t); n++) { 51991.83Skamil rv = pthread_join(t[n], NULL); 52001.83Skamil FORKEE_ASSERT(rv == 0); 52011.83Skamil } 52021.1Skamil 52031.83Skamil /* 52041.83Skamil * There is race between _exit() and pthread_join() detaching 52051.83Skamil * a thread. For simplicity kill the process after detecting 52061.83Skamil * LWP events. 52071.83Skamil */ 52081.83Skamil while (true) 52091.83Skamil continue; 52101.1Skamil 52111.83Skamil FORKEE_ASSERT(0 && "Not reached"); 52121.1Skamil } 52131.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 52141.1Skamil 52151.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52161.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52171.1Skamil 52181.1Skamil validate_status_stopped(status, sigval); 52191.1Skamil 52201.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 52211.83Skamil SYSCALL_REQUIRE( 52221.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 52231.1Skamil 52241.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 52251.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 52261.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 52271.83Skamil info.psi_siginfo.si_errno); 52281.1Skamil 52291.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 52301.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 52311.1Skamil 52321.83Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 52331.83Skamil memset(&event, 0, sizeof(event)); 52341.83Skamil if (trace_create) 52351.83Skamil event.pe_set_event |= PTRACE_LWP_CREATE; 52361.83Skamil if (trace_exit) 52371.83Skamil event.pe_set_event |= PTRACE_LWP_EXIT; 52381.83Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 52391.1Skamil 52401.13Schristos DPRINTF("Before resuming the child process where it left off and " 52411.1Skamil "without signal to be sent\n"); 52421.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 52431.1Skamil 52441.83Skamil memset(traced_lwps, 0, sizeof(traced_lwps)); 52451.1Skamil 52461.83Skamil for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) { 52471.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 52481.83Skamil "SIGTRAP\n", TWAIT_FNAME); 52491.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 52501.83Skamil child); 52511.1Skamil 52521.83Skamil validate_status_stopped(status, SIGTRAP); 52531.1Skamil 52541.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 52551.83Skamil "child\n"); 52561.83Skamil SYSCALL_REQUIRE( 52571.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 52581.1Skamil 52591.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 52601.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 52611.83Skamil "si_errno=%#x\n", 52621.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 52631.83Skamil info.psi_siginfo.si_errno); 52641.1Skamil 52651.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 52661.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 52671.1Skamil 52681.83Skamil SYSCALL_REQUIRE( 52691.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 52701.1Skamil 52711.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 52721.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 52731.1Skamil 52741.83Skamil lid = state.pe_lwp; 52751.83Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 52761.1Skamil 52771.83Skamil traced_lwps[lid - 1] = true; 52781.1Skamil 52791.83Skamil DPRINTF("Before resuming the child process where it left off " 52801.83Skamil "and without signal to be sent\n"); 52811.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 52821.83Skamil } 52831.1Skamil 52841.83Skamil for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) { 52851.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 52861.83Skamil "SIGTRAP\n", TWAIT_FNAME); 52871.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 52881.83Skamil child); 52891.1Skamil 52901.83Skamil validate_status_stopped(status, SIGTRAP); 52911.1Skamil 52921.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 52931.83Skamil "child\n"); 52941.83Skamil SYSCALL_REQUIRE( 52951.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 52961.1Skamil 52971.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 52981.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 52991.83Skamil "si_errno=%#x\n", 53001.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 53011.83Skamil info.psi_siginfo.si_errno); 53021.1Skamil 53031.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 53041.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 53051.1Skamil 53061.83Skamil SYSCALL_REQUIRE( 53071.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 53081.1Skamil 53091.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 53101.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 53111.1Skamil 53121.83Skamil lid = state.pe_lwp; 53131.83Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 53141.1Skamil 53151.83Skamil if (trace_create) { 53161.83Skamil ATF_REQUIRE(traced_lwps[lid - 1] == true); 53171.83Skamil traced_lwps[lid - 1] = false; 53181.83Skamil } 53191.1Skamil 53201.83Skamil DPRINTF("Before resuming the child process where it left off " 53211.83Skamil "and without signal to be sent\n"); 53221.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 53231.83Skamil } 53241.1Skamil 53251.83Skamil kill(child, SIGKILL); 53261.1Skamil 53271.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 53281.1Skamil TWAIT_FNAME); 53291.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 53301.1Skamil 53311.83Skamil validate_status_signaled(status, SIGKILL, 0); 53321.1Skamil 53331.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 53341.1Skamil TWAIT_FNAME); 53351.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 53361.1Skamil} 53371.1Skamil 53381.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit) \ 53391.83SkamilATF_TC(test); \ 53401.83SkamilATF_TC_HEAD(test, tc) \ 53411.83Skamil{ \ 53421.83Skamil atf_tc_set_md_var(tc, "descr", \ 53431.83Skamil "Verify spawning threads with%s tracing LWP create and" \ 53441.83Skamil "with%s tracing LWP exit", trace_create ? "" : "out", \ 53451.83Skamil trace_exit ? "" : "out"); \ 53461.83Skamil} \ 53471.83Skamil \ 53481.83SkamilATF_TC_BODY(test, tc) \ 53491.83Skamil{ \ 53501.83Skamil \ 53511.83Skamil trace_threads(trace_create, trace_exit); \ 53521.83Skamil} 53531.83Skamil 53541.83SkamilTRACE_THREADS(trace_thread1, false, false) 53551.83SkamilTRACE_THREADS(trace_thread2, false, true) 53561.83SkamilTRACE_THREADS(trace_thread3, true, false) 53571.83SkamilTRACE_THREADS(trace_thread4, true, true) 53581.83Skamil 53591.83Skamil/// ---------------------------------------------------------------------------- 53601.83Skamil 53611.84SkamilATF_TC(signal_mask_unrelated); 53621.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc) 53631.1Skamil{ 53641.1Skamil atf_tc_set_md_var(tc, "descr", 53651.1Skamil "Verify that masking single unrelated signal does not stop tracer " 53661.1Skamil "from catching other signals"); 53671.1Skamil} 53681.1Skamil 53691.84SkamilATF_TC_BODY(signal_mask_unrelated, tc) 53701.1Skamil{ 53711.1Skamil const int exitval = 5; 53721.1Skamil const int sigval = SIGSTOP; 53731.1Skamil const int sigmasked = SIGTRAP; 53741.1Skamil const int signotmasked = SIGINT; 53751.1Skamil pid_t child, wpid; 53761.1Skamil#if defined(TWAIT_HAVE_STATUS) 53771.1Skamil int status; 53781.1Skamil#endif 53791.1Skamil sigset_t intmask; 53801.1Skamil 53811.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 53821.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 53831.1Skamil if (child == 0) { 53841.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 53851.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 53861.1Skamil 53871.1Skamil sigemptyset(&intmask); 53881.1Skamil sigaddset(&intmask, sigmasked); 53891.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 53901.1Skamil 53911.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 53921.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 53931.1Skamil 53941.13Schristos DPRINTF("Before raising %s from child\n", 53951.1Skamil strsignal(signotmasked)); 53961.1Skamil FORKEE_ASSERT(raise(signotmasked) == 0); 53971.1Skamil 53981.13Schristos DPRINTF("Before exiting of the child process\n"); 53991.1Skamil _exit(exitval); 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.13Schristos DPRINTF("Before resuming the child process where it left off and " 54091.1Skamil "without signal to be sent\n"); 54101.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 54111.1Skamil 54121.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54131.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 54141.1Skamil 54151.1Skamil validate_status_stopped(status, signotmasked); 54161.1Skamil 54171.13Schristos DPRINTF("Before resuming the child process where it left off and " 54181.1Skamil "without signal to be sent\n"); 54191.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 54201.1Skamil 54211.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54221.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 54231.1Skamil 54241.1Skamil validate_status_exited(status, exitval); 54251.1Skamil 54261.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54271.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 54281.1Skamil} 54291.1Skamil 54301.84Skamil/// ---------------------------------------------------------------------------- 54311.84Skamil 54321.1Skamil#if defined(TWAIT_HAVE_PID) 54331.99Skamilstatic void 54341.99Skamilfork2_body(bool trackfork, bool trackvfork, bool trackvforkdone, bool masked, 54351.99Skamil bool ignored) 54361.1Skamil{ 54371.1Skamil const int exitval = 5; 54381.1Skamil const int exitval2 = 15; 54391.1Skamil const int sigval = SIGSTOP; 54401.99Skamil pid_t child, child2 = 0, wpid; 54411.1Skamil#if defined(TWAIT_HAVE_STATUS) 54421.1Skamil int status; 54431.1Skamil#endif 54441.1Skamil ptrace_state_t state; 54451.1Skamil const int slen = sizeof(state); 54461.1Skamil ptrace_event_t event; 54471.1Skamil const int elen = sizeof(event); 54481.99Skamil pid_t (*fn)(void); 54491.99Skamil struct sigaction sa; 54501.99Skamil struct ptrace_siginfo info; 54511.99Skamil sigset_t intmask; 54521.99Skamil struct kinfo_proc2 kp; 54531.99Skamil size_t len = sizeof(kp); 54541.99Skamil 54551.99Skamil int name[6]; 54561.99Skamil const size_t namelen = __arraycount(name); 54571.99Skamil ki_sigset_t kp_sigmask; 54581.99Skamil ki_sigset_t kp_sigignore; 54591.1Skamil 54601.99Skamil if (trackfork) 54611.99Skamil fn = fork; 54621.99Skamil if (trackvfork || trackvforkdone) 54631.99Skamil fn = vfork; 54641.14Schristos 54651.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 54661.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 54671.1Skamil if (child == 0) { 54681.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 54691.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 54701.1Skamil 54711.99Skamil if (masked) { 54721.99Skamil sigemptyset(&intmask); 54731.99Skamil sigaddset(&intmask, SIGTRAP); 54741.99Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 54751.99Skamil } 54761.99Skamil 54771.99Skamil if (ignored) { 54781.99Skamil memset(&sa, 0, sizeof(sa)); 54791.99Skamil sa.sa_handler = SIG_IGN; 54801.99Skamil sigemptyset(&sa.sa_mask); 54811.99Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 54821.99Skamil } 54831.1Skamil 54841.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 54851.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 54861.1Skamil 54871.99Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 54881.1Skamil 54891.1Skamil if (child2 == 0) 54901.1Skamil _exit(exitval2); 54911.1Skamil 54921.1Skamil FORKEE_REQUIRE_SUCCESS 54931.99Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 54941.1Skamil 54951.1Skamil forkee_status_exited(status, exitval2); 54961.1Skamil 54971.13Schristos DPRINTF("Before exiting of the child process\n"); 54981.1Skamil _exit(exitval); 54991.1Skamil } 55001.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 55011.1Skamil 55021.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 55031.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 55041.1Skamil 55051.1Skamil validate_status_stopped(status, sigval); 55061.1Skamil 55071.99Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 55081.99Skamil SYSCALL_REQUIRE( 55091.99Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 55101.99Skamil 55111.99Skamil DPRINTF("Before checking siginfo_t\n"); 55121.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 55131.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 55141.1Skamil 55151.99Skamil name[0] = CTL_KERN, 55161.99Skamil name[1] = KERN_PROC2, 55171.99Skamil name[2] = KERN_PROC_PID; 55181.99Skamil name[3] = child; 55191.99Skamil name[4] = sizeof(kp); 55201.99Skamil name[5] = 1; 55211.1Skamil 55221.99Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 55231.1Skamil 55241.99Skamil if (masked) 55251.99Skamil kp_sigmask = kp.p_sigmask; 55261.1Skamil 55271.99Skamil if (ignored) 55281.99Skamil kp_sigignore = kp.p_sigignore; 55291.1Skamil 55301.99Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 55311.99Skamil trackfork ? "|PTRACE_FORK" : "", 55321.99Skamil trackvfork ? "|PTRACE_VFORK" : "", 55331.99Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 55341.99Skamil event.pe_set_event = 0; 55351.99Skamil if (trackfork) 55361.99Skamil event.pe_set_event |= PTRACE_FORK; 55371.99Skamil if (trackvfork) 55381.99Skamil event.pe_set_event |= PTRACE_VFORK; 55391.99Skamil if (trackvforkdone) 55401.99Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 55411.99Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 55421.1Skamil 55431.99Skamil DPRINTF("Before resuming the child process where it left off and " 55441.99Skamil "without signal to be sent\n"); 55451.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 55461.1Skamil 55471.99Skamil if (trackfork || trackvfork) { 55481.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 55491.99Skamil child); 55501.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 55511.99Skamil child); 55521.1Skamil 55531.99Skamil validate_status_stopped(status, SIGTRAP); 55541.1Skamil 55551.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 55561.1Skamil 55571.99Skamil if (masked) { 55581.99Skamil DPRINTF("kp_sigmask=" 55591.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 55601.99Skamil PRIx32 "\n", 55611.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 55621.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 55631.1Skamil 55641.99Skamil DPRINTF("kp.p_sigmask=" 55651.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 55661.99Skamil PRIx32 "\n", 55671.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 55681.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 55691.1Skamil 55701.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 55711.99Skamil sizeof(kp_sigmask))); 55721.99Skamil } 55731.1Skamil 55741.99Skamil if (ignored) { 55751.99Skamil DPRINTF("kp_sigignore=" 55761.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 55771.99Skamil PRIx32 "\n", 55781.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 55791.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 55801.1Skamil 55811.99Skamil DPRINTF("kp.p_sigignore=" 55821.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 55831.99Skamil PRIx32 "\n", 55841.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 55851.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 55861.1Skamil 55871.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 55881.99Skamil sizeof(kp_sigignore))); 55891.99Skamil } 55901.1Skamil 55911.99Skamil SYSCALL_REQUIRE( 55921.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 55931.99Skamil if (trackfork) { 55941.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 55951.99Skamil PTRACE_FORK); 55961.99Skamil } 55971.99Skamil if (trackvfork) { 55981.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 55991.99Skamil PTRACE_VFORK); 56001.99Skamil } 56011.1Skamil 56021.99Skamil child2 = state.pe_other_pid; 56031.99Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 56041.1Skamil 56051.99Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 56061.99Skamil "%d\n", TWAIT_FNAME, child2, child); 56071.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 56081.99Skamil child2); 56091.1Skamil 56101.99Skamil validate_status_stopped(status, SIGTRAP); 56111.1Skamil 56121.99Skamil name[3] = child2; 56131.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 56141.1Skamil 56151.99Skamil if (masked) { 56161.99Skamil DPRINTF("kp_sigmask=" 56171.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 56181.99Skamil PRIx32 "\n", 56191.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 56201.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 56211.1Skamil 56221.99Skamil DPRINTF("kp.p_sigmask=" 56231.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 56241.99Skamil PRIx32 "\n", 56251.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 56261.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 56271.14Schristos 56281.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 56291.99Skamil sizeof(kp_sigmask))); 56301.99Skamil } 56311.1Skamil 56321.99Skamil if (ignored) { 56331.99Skamil DPRINTF("kp_sigignore=" 56341.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 56351.99Skamil PRIx32 "\n", 56361.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 56371.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 56381.1Skamil 56391.99Skamil DPRINTF("kp.p_sigignore=" 56401.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 56411.99Skamil PRIx32 "\n", 56421.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 56431.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 56441.1Skamil 56451.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 56461.99Skamil sizeof(kp_sigignore))); 56471.99Skamil } 56481.1Skamil 56491.99Skamil SYSCALL_REQUIRE( 56501.99Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 56511.99Skamil if (trackfork) { 56521.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 56531.99Skamil PTRACE_FORK); 56541.99Skamil } 56551.99Skamil if (trackvfork) { 56561.99Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 56571.99Skamil PTRACE_VFORK); 56581.99Skamil } 56591.1Skamil 56601.99Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 56611.1Skamil 56621.99Skamil DPRINTF("Before resuming the forkee process where it left off " 56631.99Skamil "and without signal to be sent\n"); 56641.99Skamil SYSCALL_REQUIRE( 56651.99Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 56661.1Skamil 56671.99Skamil DPRINTF("Before resuming the child process where it left off " 56681.99Skamil "and without signal to be sent\n"); 56691.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56701.1Skamil } 56711.1Skamil 56721.99Skamil if (trackvforkdone) { 56731.99Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 56741.99Skamil child); 56751.99Skamil TWAIT_REQUIRE_SUCCESS( 56761.99Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 56771.1Skamil 56781.99Skamil validate_status_stopped(status, SIGTRAP); 56791.1Skamil 56801.99Skamil name[3] = child; 56811.99Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 56821.1Skamil 56831.102Skamil /* 56841.102Skamil * SIGCHLD is now pending in the signal queue and 56851.102Skamil * the kernel presents it to userland as a masked signal. 56861.102Skamil */ 56871.102Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 56881.102Skamil 56891.99Skamil if (masked) { 56901.99Skamil DPRINTF("kp_sigmask=" 56911.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 56921.99Skamil PRIx32 "\n", 56931.99Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 56941.99Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 56951.1Skamil 56961.99Skamil DPRINTF("kp.p_sigmask=" 56971.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 56981.99Skamil PRIx32 "\n", 56991.99Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 57001.99Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 57011.1Skamil 57021.99Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 57031.99Skamil sizeof(kp_sigmask))); 57041.99Skamil } 57051.1Skamil 57061.99Skamil if (ignored) { 57071.99Skamil DPRINTF("kp_sigignore=" 57081.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 57091.99Skamil PRIx32 "\n", 57101.99Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 57111.99Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 57121.1Skamil 57131.99Skamil DPRINTF("kp.p_sigignore=" 57141.99Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 57151.99Skamil PRIx32 "\n", 57161.99Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 57171.99Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 57181.1Skamil 57191.99Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 57201.99Skamil sizeof(kp_sigignore))); 57211.99Skamil } 57221.1Skamil 57231.99Skamil SYSCALL_REQUIRE( 57241.99Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 57251.99Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 57261.1Skamil 57271.99Skamil child2 = state.pe_other_pid; 57281.99Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 57291.99Skamil child2); 57301.1Skamil 57311.99Skamil DPRINTF("Before resuming the child process where it left off " 57321.99Skamil "and without signal to be sent\n"); 57331.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 57341.99Skamil } 57351.1Skamil 57361.99Skamil if (trackfork || trackvfork) { 57371.99Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 57381.99Skamil "\n", TWAIT_FNAME); 57391.99Skamil TWAIT_REQUIRE_SUCCESS( 57401.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 57411.1Skamil 57421.99Skamil validate_status_exited(status, exitval2); 57431.1Skamil 57441.99Skamil DPRINTF("Before calling %s() for the forkee - expected no " 57451.99Skamil "process\n", TWAIT_FNAME); 57461.99Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 57471.99Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 57481.99Skamil } 57491.1Skamil 57501.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 57511.1Skamil "SIGCHLD\n", TWAIT_FNAME); 57521.57Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57531.1Skamil 57541.1Skamil validate_status_stopped(status, SIGCHLD); 57551.1Skamil 57561.57Skamil DPRINTF("Before resuming the child process where it left off and " 57571.1Skamil "without signal to be sent\n"); 57581.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 57591.1Skamil 57601.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 57611.1Skamil TWAIT_FNAME); 57621.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57631.1Skamil 57641.1Skamil validate_status_exited(status, exitval); 57651.1Skamil 57661.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 57671.57Skamil TWAIT_FNAME); 57681.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 57691.1Skamil} 57701.1Skamil 57711.99Skamil#define FORK2_TEST(name,trackfork,trackvfork,trackvforkdone, \ 57721.99Skamil masked,ignored) \ 57731.99SkamilATF_TC(name); \ 57741.99SkamilATF_TC_HEAD(name, tc) \ 57751.99Skamil{ \ 57761.99Skamil atf_tc_set_md_var(tc, "descr", "Verify that %s%s%s is caught " \ 57771.99Skamil "regardless of signal %s%s", \ 57781.99Skamil trackfork ? "PTRACE_FORK" : "", \ 57791.99Skamil trackvfork ? "PTRACE_VFORK" : "", \ 57801.99Skamil trackvforkdone ? "PTRACE_VFORK_DONE" : "", \ 57811.99Skamil masked ? "masked" : "", ignored ? "ignored" : ""); \ 57821.99Skamil} \ 57831.99Skamil \ 57841.99SkamilATF_TC_BODY(name, tc) \ 57851.99Skamil{ \ 57861.99Skamil \ 57871.99Skamil fork2_body(trackfork, trackvfork, trackvforkdone, masked, \ 57881.99Skamil ignored); \ 57891.1Skamil} 57901.1Skamil 57911.99SkamilFORK2_TEST(fork_singalmasked, true, false, false, true, false) 57921.99SkamilFORK2_TEST(fork_singalignored, true, false, false, false, true) 57931.110Skamil#if TEST_VFORK_ENABLED 57941.99SkamilFORK2_TEST(vfork_singalmasked, false, true, false, true, false) 57951.99SkamilFORK2_TEST(vfork_singalignored, false, true, false, false, true) 57961.99SkamilFORK2_TEST(vforkdone_singalmasked, false, false, true, true, false) 57971.99SkamilFORK2_TEST(vforkdone_singalignored, false, false, true, false, true) 57981.1Skamil#endif 57991.110Skamil#endif 58001.1Skamil 58011.99Skamil/// ---------------------------------------------------------------------------- 58021.1Skamil 58031.83Skamilvolatile lwpid_t the_lwp_id = 0; 58041.83Skamil 58051.83Skamilstatic void 58061.83Skamillwp_main_func(void *arg) 58071.83Skamil{ 58081.83Skamil the_lwp_id = _lwp_self(); 58091.83Skamil _lwp_exit(); 58101.83Skamil} 58111.83Skamil 58121.1SkamilATF_TC(signal9); 58131.1SkamilATF_TC_HEAD(signal9, tc) 58141.1Skamil{ 58151.1Skamil atf_tc_set_md_var(tc, "descr", 58161.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 58171.1Skamil "catching PTRACE_LWP_CREATE breakpoint"); 58181.1Skamil} 58191.1Skamil 58201.1SkamilATF_TC_BODY(signal9, tc) 58211.1Skamil{ 58221.1Skamil const int exitval = 5; 58231.1Skamil const int sigval = SIGSTOP; 58241.1Skamil const int sigmasked = SIGTRAP; 58251.1Skamil pid_t child, wpid; 58261.1Skamil#if defined(TWAIT_HAVE_STATUS) 58271.1Skamil int status; 58281.1Skamil#endif 58291.1Skamil sigset_t intmask; 58301.1Skamil ptrace_state_t state; 58311.1Skamil const int slen = sizeof(state); 58321.1Skamil ptrace_event_t event; 58331.1Skamil const int elen = sizeof(event); 58341.1Skamil ucontext_t uc; 58351.1Skamil lwpid_t lid; 58361.1Skamil static const size_t ssize = 16*1024; 58371.1Skamil void *stack; 58381.1Skamil 58391.14Schristos atf_tc_expect_fail("PR kern/51918"); 58401.14Schristos 58411.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 58421.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 58431.1Skamil if (child == 0) { 58441.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 58451.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 58461.1Skamil 58471.1Skamil sigemptyset(&intmask); 58481.1Skamil sigaddset(&intmask, sigmasked); 58491.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 58501.1Skamil 58511.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 58521.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 58531.1Skamil 58541.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 58551.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 58561.1Skamil 58571.13Schristos DPRINTF("Before making context for new lwp in child\n"); 58581.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 58591.1Skamil 58601.13Schristos DPRINTF("Before creating new in child\n"); 58611.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 58621.1Skamil 58631.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 58641.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 58651.1Skamil 58661.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 58671.1Skamil "are the same\n", lid, the_lwp_id); 58681.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 58691.1Skamil 58701.13Schristos DPRINTF("Before exiting of the child process\n"); 58711.1Skamil _exit(exitval); 58721.1Skamil } 58731.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 58741.1Skamil 58751.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 58761.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 58771.1Skamil 58781.1Skamil validate_status_stopped(status, sigval); 58791.1Skamil 58801.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 58811.1Skamil event.pe_set_event = PTRACE_LWP_CREATE; 58821.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 58831.1Skamil 58841.13Schristos DPRINTF("Before resuming the child process where it left off and " 58851.1Skamil "without signal to be sent\n"); 58861.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 58871.1Skamil 58881.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 58891.1Skamil "SIGTRAP\n", TWAIT_FNAME); 58901.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 58911.1Skamil 58921.1Skamil validate_status_stopped(status, sigmasked); 58931.1Skamil 58941.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 58951.1Skamil 58961.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE); 58971.1Skamil 58981.1Skamil lid = state.pe_lwp; 58991.13Schristos DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 59001.1Skamil 59011.13Schristos DPRINTF("Before resuming the child process where it left off and " 59021.1Skamil "without signal to be sent\n"); 59031.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 59041.1Skamil 59051.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 59061.1Skamil TWAIT_FNAME); 59071.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 59081.1Skamil 59091.1Skamil validate_status_exited(status, exitval); 59101.1Skamil 59111.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 59121.1Skamil TWAIT_FNAME); 59131.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 59141.1Skamil} 59151.1Skamil 59161.1SkamilATF_TC(signal10); 59171.1SkamilATF_TC_HEAD(signal10, tc) 59181.1Skamil{ 59191.1Skamil atf_tc_set_md_var(tc, "descr", 59201.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 59211.1Skamil "catching PTRACE_LWP_EXIT breakpoint"); 59221.1Skamil} 59231.1Skamil 59241.1SkamilATF_TC_BODY(signal10, tc) 59251.1Skamil{ 59261.1Skamil const int exitval = 5; 59271.1Skamil const int sigval = SIGSTOP; 59281.1Skamil const int sigmasked = SIGTRAP; 59291.1Skamil pid_t child, wpid; 59301.1Skamil#if defined(TWAIT_HAVE_STATUS) 59311.1Skamil int status; 59321.1Skamil#endif 59331.1Skamil sigset_t intmask; 59341.1Skamil ptrace_state_t state; 59351.1Skamil const int slen = sizeof(state); 59361.1Skamil ptrace_event_t event; 59371.1Skamil const int elen = sizeof(event); 59381.1Skamil ucontext_t uc; 59391.1Skamil lwpid_t lid; 59401.1Skamil static const size_t ssize = 16*1024; 59411.1Skamil void *stack; 59421.1Skamil 59431.14Schristos atf_tc_expect_fail("PR kern/51918"); 59441.14Schristos 59451.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 59461.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 59471.1Skamil if (child == 0) { 59481.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 59491.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 59501.1Skamil 59511.1Skamil sigemptyset(&intmask); 59521.1Skamil sigaddset(&intmask, sigmasked); 59531.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 59541.1Skamil 59551.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 59561.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 59571.1Skamil 59581.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 59591.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 59601.1Skamil 59611.13Schristos DPRINTF("Before making context for new lwp in child\n"); 59621.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 59631.1Skamil 59641.13Schristos DPRINTF("Before creating new in child\n"); 59651.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 59661.1Skamil 59671.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 59681.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 59691.1Skamil 59701.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 59711.1Skamil "are the same\n", lid, the_lwp_id); 59721.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 59731.1Skamil 59741.13Schristos DPRINTF("Before exiting of the child process\n"); 59751.1Skamil _exit(exitval); 59761.1Skamil } 59771.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 59781.1Skamil 59791.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 59801.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 59811.1Skamil 59821.1Skamil validate_status_stopped(status, sigval); 59831.1Skamil 59841.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 59851.1Skamil event.pe_set_event = PTRACE_LWP_EXIT; 59861.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 59871.1Skamil 59881.13Schristos DPRINTF("Before resuming the child process where it left off and " 59891.1Skamil "without signal to be sent\n"); 59901.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 59911.1Skamil 59921.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 59931.1Skamil "SIGTRAP\n", TWAIT_FNAME); 59941.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 59951.1Skamil 59961.1Skamil validate_status_stopped(status, sigmasked); 59971.1Skamil 59981.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 59991.1Skamil 60001.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT); 60011.1Skamil 60021.1Skamil lid = state.pe_lwp; 60031.13Schristos DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 60041.1Skamil 60051.13Schristos DPRINTF("Before resuming the child process where it left off and " 60061.1Skamil "without signal to be sent\n"); 60071.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60081.1Skamil 60091.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 60101.1Skamil TWAIT_FNAME); 60111.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60121.1Skamil 60131.1Skamil validate_status_exited(status, exitval); 60141.1Skamil 60151.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 60161.1Skamil TWAIT_FNAME); 60171.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 60181.1Skamil} 60191.1Skamil 60201.1Skamilstatic void 60211.1Skamillwp_main_stop(void *arg) 60221.1Skamil{ 60231.1Skamil the_lwp_id = _lwp_self(); 60241.1Skamil 60251.1Skamil raise(SIGTRAP); 60261.1Skamil 60271.1Skamil _lwp_exit(); 60281.1Skamil} 60291.1Skamil 60301.1SkamilATF_TC(suspend1); 60311.1SkamilATF_TC_HEAD(suspend1, tc) 60321.1Skamil{ 60331.1Skamil atf_tc_set_md_var(tc, "descr", 60341.1Skamil "Verify that a thread can be suspended by a debugger and later " 60351.1Skamil "resumed by a tracee"); 60361.1Skamil} 60371.1Skamil 60381.1SkamilATF_TC_BODY(suspend1, tc) 60391.1Skamil{ 60401.1Skamil const int exitval = 5; 60411.1Skamil const int sigval = SIGSTOP; 60421.1Skamil pid_t child, wpid; 60431.1Skamil#if defined(TWAIT_HAVE_STATUS) 60441.1Skamil int status; 60451.1Skamil#endif 60461.1Skamil ucontext_t uc; 60471.1Skamil lwpid_t lid; 60481.1Skamil static const size_t ssize = 16*1024; 60491.1Skamil void *stack; 60501.1Skamil struct ptrace_lwpinfo pl; 60511.1Skamil struct ptrace_siginfo psi; 60521.1Skamil volatile int go = 0; 60531.1Skamil 60541.17Skamil // Feature pending for refactoring 60551.17Skamil atf_tc_expect_fail("PR kern/51995"); 60561.17Skamil 60571.16Skamil // Hangs with qemu 60581.16Skamil ATF_REQUIRE(0 && "In order to get reliable failure, abort"); 60591.16Skamil 60601.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 60611.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 60621.1Skamil if (child == 0) { 60631.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 60641.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 60651.1Skamil 60661.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 60671.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 60681.1Skamil 60691.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 60701.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 60711.1Skamil 60721.13Schristos DPRINTF("Before making context for new lwp in child\n"); 60731.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 60741.1Skamil 60751.13Schristos DPRINTF("Before creating new in child\n"); 60761.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 60771.1Skamil 60781.1Skamil while (go == 0) 60791.1Skamil continue; 60801.1Skamil 60811.1Skamil raise(SIGINT); 60821.1Skamil 60831.1Skamil FORKEE_ASSERT(_lwp_continue(lid) == 0); 60841.1Skamil 60851.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 60861.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 60871.1Skamil 60881.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 60891.1Skamil "are the same\n", lid, the_lwp_id); 60901.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 60911.1Skamil 60921.13Schristos DPRINTF("Before exiting of the child process\n"); 60931.1Skamil _exit(exitval); 60941.1Skamil } 60951.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 60961.1Skamil 60971.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 60981.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60991.1Skamil 61001.1Skamil validate_status_stopped(status, sigval); 61011.1Skamil 61021.13Schristos DPRINTF("Before resuming the child process where it left off and " 61031.1Skamil "without signal to be sent\n"); 61041.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 61051.1Skamil 61061.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 61071.1Skamil "SIGTRAP\n", TWAIT_FNAME); 61081.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61091.1Skamil 61101.1Skamil validate_status_stopped(status, SIGTRAP); 61111.1Skamil 61121.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 61131.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 61141.1Skamil 61151.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 61161.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 61171.1Skamil 61181.13Schristos DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n", 61191.1Skamil child, getpid()); 61201.13Schristos SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1); 61211.1Skamil 61221.13Schristos DPRINTF("Before resuming the child process where it left off and " 61231.1Skamil "without signal to be sent\n"); 61241.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 61251.1Skamil 61261.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 61271.1Skamil "SIGINT\n", TWAIT_FNAME); 61281.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61291.1Skamil 61301.1Skamil validate_status_stopped(status, SIGINT); 61311.1Skamil 61321.1Skamil pl.pl_lwpid = 0; 61331.1Skamil 61341.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 61351.1Skamil while (pl.pl_lwpid != 0) { 61361.1Skamil 61371.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 61381.1Skamil switch (pl.pl_lwpid) { 61391.1Skamil case 1: 61401.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 61411.1Skamil break; 61421.1Skamil case 2: 61431.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 61441.1Skamil break; 61451.1Skamil } 61461.1Skamil } 61471.1Skamil 61481.13Schristos DPRINTF("Before resuming the child process where it left off and " 61491.1Skamil "without signal to be sent\n"); 61501.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 61511.1Skamil 61521.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 61531.1Skamil TWAIT_FNAME); 61541.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 61551.1Skamil 61561.1Skamil validate_status_exited(status, exitval); 61571.1Skamil 61581.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 61591.1Skamil TWAIT_FNAME); 61601.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 61611.1Skamil} 61621.1Skamil 61631.1SkamilATF_TC(suspend2); 61641.1SkamilATF_TC_HEAD(suspend2, tc) 61651.1Skamil{ 61661.1Skamil atf_tc_set_md_var(tc, "descr", 61671.1Skamil "Verify that the while the only thread within a process is " 61681.1Skamil "suspended, the whole process cannot be unstopped"); 61691.1Skamil} 61701.1Skamil 61711.1SkamilATF_TC_BODY(suspend2, tc) 61721.1Skamil{ 61731.1Skamil const int exitval = 5; 61741.1Skamil const int sigval = SIGSTOP; 61751.1Skamil pid_t child, wpid; 61761.1Skamil#if defined(TWAIT_HAVE_STATUS) 61771.1Skamil int status; 61781.1Skamil#endif 61791.1Skamil struct ptrace_siginfo psi; 61801.1Skamil 61811.17Skamil // Feature pending for refactoring 61821.17Skamil atf_tc_expect_fail("PR kern/51995"); 61831.17Skamil 61841.16Skamil // Hangs with qemu 61851.16Skamil ATF_REQUIRE(0 && "In order to get reliable failure, abort"); 61861.16Skamil 61871.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 61881.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 61891.1Skamil if (child == 0) { 61901.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 61911.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 61921.1Skamil 61931.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 61941.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 61951.1Skamil 61961.13Schristos DPRINTF("Before exiting of the child process\n"); 61971.1Skamil _exit(exitval); 61981.1Skamil } 61991.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 62001.1Skamil 62011.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 62021.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62031.1Skamil 62041.1Skamil validate_status_stopped(status, sigval); 62051.1Skamil 62061.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 62071.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 62081.1Skamil 62091.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 62101.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 62111.1Skamil 62121.13Schristos DPRINTF("Before resuming the child process where it left off and " 62131.1Skamil "without signal to be sent\n"); 62141.1Skamil ATF_REQUIRE_ERRNO(EDEADLK, 62151.1Skamil ptrace(PT_CONTINUE, child, (void *)1, 0) == -1); 62161.1Skamil 62171.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 62181.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 62191.1Skamil 62201.13Schristos DPRINTF("Before resuming the child process where it left off and " 62211.1Skamil "without signal to be sent\n"); 62221.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 62231.1Skamil 62241.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 62251.1Skamil TWAIT_FNAME); 62261.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 62271.1Skamil 62281.1Skamil validate_status_exited(status, exitval); 62291.1Skamil 62301.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 62311.1Skamil TWAIT_FNAME); 62321.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 62331.1Skamil} 62341.1Skamil 62351.1SkamilATF_TC(resume1); 62361.1SkamilATF_TC_HEAD(resume1, tc) 62371.1Skamil{ 62381.1Skamil atf_tc_set_md_var(tc, "timeout", "5"); 62391.1Skamil atf_tc_set_md_var(tc, "descr", 62401.1Skamil "Verify that a thread can be suspended by a debugger and later " 62411.1Skamil "resumed by the debugger"); 62421.1Skamil} 62431.1Skamil 62441.1SkamilATF_TC_BODY(resume1, tc) 62451.1Skamil{ 62461.1Skamil struct msg_fds fds; 62471.1Skamil const int exitval = 5; 62481.1Skamil const int sigval = SIGSTOP; 62491.1Skamil pid_t child, wpid; 62501.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 62511.1Skamil#if defined(TWAIT_HAVE_STATUS) 62521.1Skamil int status; 62531.1Skamil#endif 62541.1Skamil ucontext_t uc; 62551.1Skamil lwpid_t lid; 62561.1Skamil static const size_t ssize = 16*1024; 62571.1Skamil void *stack; 62581.1Skamil struct ptrace_lwpinfo pl; 62591.1Skamil struct ptrace_siginfo psi; 62601.1Skamil 62611.17Skamil // Feature pending for refactoring 62621.17Skamil atf_tc_expect_fail("PR kern/51995"); 62631.17Skamil 62641.15Schristos // Hangs with qemu 62651.15Schristos ATF_REQUIRE(0 && "In order to get reliable failure, abort"); 62661.1Skamil 62671.13Schristos SYSCALL_REQUIRE(msg_open(&fds) == 0); 62681.1Skamil 62691.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 62701.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 62711.1Skamil if (child == 0) { 62721.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 62731.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 62741.1Skamil 62751.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 62761.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 62771.1Skamil 62781.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 62791.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 62801.1Skamil 62811.13Schristos DPRINTF("Before making context for new lwp in child\n"); 62821.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 62831.1Skamil 62841.13Schristos DPRINTF("Before creating new in child\n"); 62851.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 62861.1Skamil 62871.1Skamil CHILD_TO_PARENT("Message", fds, msg); 62881.1Skamil 62891.1Skamil raise(SIGINT); 62901.1Skamil 62911.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 62921.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 62931.1Skamil 62941.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 62951.1Skamil "are the same\n", lid, the_lwp_id); 62961.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 62971.1Skamil 62981.13Schristos DPRINTF("Before exiting of the child process\n"); 62991.1Skamil _exit(exitval); 63001.1Skamil } 63011.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 63021.1Skamil 63031.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 63041.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63051.1Skamil 63061.1Skamil validate_status_stopped(status, sigval); 63071.1Skamil 63081.13Schristos DPRINTF("Before resuming the child process where it left off and " 63091.1Skamil "without signal to be sent\n"); 63101.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63111.1Skamil 63121.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 63131.1Skamil "SIGTRAP\n", TWAIT_FNAME); 63141.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63151.1Skamil 63161.1Skamil validate_status_stopped(status, SIGTRAP); 63171.1Skamil 63181.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 63191.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 63201.1Skamil 63211.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 63221.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 63231.1Skamil 63241.1Skamil PARENT_FROM_CHILD("Message", fds, msg); 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 stopped " 63311.1Skamil "SIGINT\n", TWAIT_FNAME); 63321.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63331.1Skamil 63341.1Skamil validate_status_stopped(status, SIGINT); 63351.1Skamil 63361.1Skamil pl.pl_lwpid = 0; 63371.1Skamil 63381.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 63391.1Skamil while (pl.pl_lwpid != 0) { 63401.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 63411.1Skamil switch (pl.pl_lwpid) { 63421.1Skamil case 1: 63431.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 63441.1Skamil break; 63451.1Skamil case 2: 63461.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 63471.1Skamil break; 63481.1Skamil } 63491.1Skamil } 63501.1Skamil 63511.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 63521.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 63531.1Skamil 63541.13Schristos DPRINTF("Before resuming the child process where it left off and " 63551.1Skamil "without signal to be sent\n"); 63561.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 63571.1Skamil 63581.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 63591.1Skamil TWAIT_FNAME); 63601.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 63611.1Skamil 63621.1Skamil validate_status_exited(status, exitval); 63631.1Skamil 63641.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 63651.1Skamil TWAIT_FNAME); 63661.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 63671.1Skamil 63681.1Skamil msg_close(&fds); 63691.1Skamil 63701.13Schristos DPRINTF("XXX: Test worked this time but for consistency timeout it\n"); 63711.1Skamil sleep(10); 63721.1Skamil} 63731.1Skamil 63741.1SkamilATF_TC(syscall1); 63751.1SkamilATF_TC_HEAD(syscall1, tc) 63761.1Skamil{ 63771.1Skamil atf_tc_set_md_var(tc, "descr", 63781.1Skamil "Verify that getpid(2) can be traced with PT_SYSCALL"); 63791.1Skamil} 63801.1Skamil 63811.1SkamilATF_TC_BODY(syscall1, tc) 63821.1Skamil{ 63831.1Skamil const int exitval = 5; 63841.1Skamil const int sigval = SIGSTOP; 63851.1Skamil pid_t child, wpid; 63861.1Skamil#if defined(TWAIT_HAVE_STATUS) 63871.1Skamil int status; 63881.1Skamil#endif 63891.1Skamil struct ptrace_siginfo info; 63901.1Skamil memset(&info, 0, sizeof(info)); 63911.1Skamil 63921.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 63931.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 63941.1Skamil if (child == 0) { 63951.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 63961.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 63971.1Skamil 63981.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 63991.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 64001.1Skamil 64011.1Skamil syscall(SYS_getpid); 64021.1Skamil 64031.13Schristos DPRINTF("Before exiting of the child process\n"); 64041.1Skamil _exit(exitval); 64051.1Skamil } 64061.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 64071.1Skamil 64081.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 64091.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64101.1Skamil 64111.1Skamil validate_status_stopped(status, sigval); 64121.1Skamil 64131.13Schristos DPRINTF("Before resuming the child process where it left off and " 64141.1Skamil "without signal to be sent\n"); 64151.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 64161.1Skamil 64171.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 64181.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64191.1Skamil 64201.1Skamil validate_status_stopped(status, SIGTRAP); 64211.1Skamil 64221.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 64231.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 64241.1Skamil 64251.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 64261.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 64271.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 64281.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE); 64291.1Skamil 64301.13Schristos DPRINTF("Before resuming the child process where it left off and " 64311.1Skamil "without signal to be sent\n"); 64321.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 64331.1Skamil 64341.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 64351.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64361.1Skamil 64371.1Skamil validate_status_stopped(status, SIGTRAP); 64381.1Skamil 64391.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 64401.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 64411.1Skamil 64421.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 64431.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 64441.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 64451.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX); 64461.1Skamil 64471.13Schristos DPRINTF("Before resuming the child process where it left off and " 64481.1Skamil "without signal to be sent\n"); 64491.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 64501.1Skamil 64511.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 64521.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64531.1Skamil 64541.1Skamil validate_status_exited(status, exitval); 64551.1Skamil 64561.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 64571.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 64581.1Skamil} 64591.1Skamil 64601.1SkamilATF_TC(syscallemu1); 64611.1SkamilATF_TC_HEAD(syscallemu1, tc) 64621.1Skamil{ 64631.1Skamil atf_tc_set_md_var(tc, "descr", 64641.1Skamil "Verify that exit(2) can be intercepted with PT_SYSCALLEMU"); 64651.1Skamil} 64661.1Skamil 64671.1SkamilATF_TC_BODY(syscallemu1, tc) 64681.1Skamil{ 64691.1Skamil const int exitval = 5; 64701.1Skamil const int sigval = SIGSTOP; 64711.1Skamil pid_t child, wpid; 64721.1Skamil#if defined(TWAIT_HAVE_STATUS) 64731.1Skamil int status; 64741.1Skamil#endif 64751.1Skamil 64761.6Skamil#if defined(__sparc__) && !defined(__sparc64__) 64771.6Skamil /* syscallemu does not work on sparc (32-bit) */ 64781.6Skamil atf_tc_expect_fail("PR kern/52166"); 64791.6Skamil#endif 64801.6Skamil 64811.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 64821.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 64831.1Skamil if (child == 0) { 64841.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 64851.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 64861.1Skamil 64871.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 64881.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 64891.1Skamil 64901.1Skamil syscall(SYS_exit, 100); 64911.1Skamil 64921.13Schristos DPRINTF("Before exiting of the child process\n"); 64931.1Skamil _exit(exitval); 64941.1Skamil } 64951.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 64961.1Skamil 64971.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 64981.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 64991.1Skamil 65001.1Skamil validate_status_stopped(status, sigval); 65011.1Skamil 65021.13Schristos DPRINTF("Before resuming the child process where it left off and " 65031.1Skamil "without signal to be sent\n"); 65041.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 65051.1Skamil 65061.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65071.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65081.1Skamil 65091.1Skamil validate_status_stopped(status, SIGTRAP); 65101.1Skamil 65111.13Schristos DPRINTF("Set SYSCALLEMU for intercepted syscall\n"); 65121.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1); 65131.1Skamil 65141.13Schristos DPRINTF("Before resuming the child process where it left off and " 65151.1Skamil "without signal to be sent\n"); 65161.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 65171.1Skamil 65181.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65191.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65201.1Skamil 65211.1Skamil validate_status_stopped(status, SIGTRAP); 65221.1Skamil 65231.13Schristos DPRINTF("Before resuming the child process where it left off and " 65241.1Skamil "without signal to be sent\n"); 65251.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 65261.1Skamil 65271.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65281.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65291.1Skamil 65301.1Skamil validate_status_exited(status, exitval); 65311.1Skamil 65321.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65331.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 65341.1Skamil} 65351.1Skamil 65361.103Skamil/// ---------------------------------------------------------------------------- 65371.103Skamil 65381.106Skamilstatic void 65391.106Skamilclone_body(int flags, bool trackfork, bool trackvfork, 65401.106Skamil bool trackvforkdone) 65411.106Skamil{ 65421.106Skamil const int exitval = 5; 65431.106Skamil const int exitval2 = 15; 65441.106Skamil const int sigval = SIGSTOP; 65451.106Skamil pid_t child, child2 = 0, wpid; 65461.106Skamil#if defined(TWAIT_HAVE_STATUS) 65471.106Skamil int status; 65481.106Skamil#endif 65491.106Skamil ptrace_state_t state; 65501.106Skamil const int slen = sizeof(state); 65511.106Skamil ptrace_event_t event; 65521.106Skamil const int elen = sizeof(event); 65531.106Skamil 65541.106Skamil const size_t stack_size = 1024 * 1024; 65551.106Skamil void *stack, *stack_base; 65561.106Skamil 65571.106Skamil stack = malloc(stack_size); 65581.106Skamil ATF_REQUIRE(stack != NULL); 65591.106Skamil 65601.106Skamil#ifdef __MACHINE_STACK_GROWS_UP 65611.106Skamil stack_base = stack; 65621.106Skamil#else 65631.106Skamil stack_base = (char *)stack + stack_size; 65641.106Skamil#endif 65651.106Skamil 65661.106Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 65671.106Skamil SYSCALL_REQUIRE((child = fork()) != -1); 65681.106Skamil if (child == 0) { 65691.106Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 65701.106Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 65711.106Skamil 65721.106Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 65731.106Skamil FORKEE_ASSERT(raise(sigval) == 0); 65741.106Skamil 65751.106Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 65761.106Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 65771.106Skamil 65781.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 65791.106Skamil child2); 65801.106Skamil 65811.106Skamil // XXX WALLSIG? 65821.106Skamil FORKEE_REQUIRE_SUCCESS 65831.106Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 65841.106Skamil 65851.106Skamil forkee_status_exited(status, exitval2); 65861.106Skamil 65871.106Skamil DPRINTF("Before exiting of the child process\n"); 65881.106Skamil _exit(exitval); 65891.106Skamil } 65901.106Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 65911.106Skamil 65921.106Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 65931.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 65941.106Skamil 65951.106Skamil validate_status_stopped(status, sigval); 65961.106Skamil 65971.106Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 65981.106Skamil trackfork ? "|PTRACE_FORK" : "", 65991.106Skamil trackvfork ? "|PTRACE_VFORK" : "", 66001.106Skamil trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 66011.106Skamil event.pe_set_event = 0; 66021.106Skamil if (trackfork) 66031.106Skamil event.pe_set_event |= PTRACE_FORK; 66041.106Skamil if (trackvfork) 66051.106Skamil event.pe_set_event |= PTRACE_VFORK; 66061.106Skamil if (trackvforkdone) 66071.106Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 66081.106Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 66091.106Skamil 66101.106Skamil DPRINTF("Before resuming the child process where it left off and " 66111.106Skamil "without signal to be sent\n"); 66121.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66131.106Skamil 66141.106Skamil#if defined(TWAIT_HAVE_PID) 66151.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 66161.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 66171.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 66181.106Skamil child); 66191.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 66201.106Skamil child); 66211.106Skamil 66221.106Skamil validate_status_stopped(status, SIGTRAP); 66231.106Skamil 66241.106Skamil SYSCALL_REQUIRE( 66251.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 66261.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 66271.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 66281.106Skamil PTRACE_FORK); 66291.106Skamil } 66301.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 66311.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 66321.106Skamil PTRACE_VFORK); 66331.106Skamil } 66341.106Skamil 66351.106Skamil child2 = state.pe_other_pid; 66361.106Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 66371.106Skamil 66381.106Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 66391.106Skamil "%d\n", TWAIT_FNAME, child2, child); 66401.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 66411.106Skamil child2); 66421.106Skamil 66431.106Skamil validate_status_stopped(status, SIGTRAP); 66441.106Skamil 66451.106Skamil SYSCALL_REQUIRE( 66461.106Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 66471.106Skamil if (trackfork && !(flags & CLONE_VFORK)) { 66481.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 66491.106Skamil PTRACE_FORK); 66501.106Skamil } 66511.106Skamil if (trackvfork && (flags & CLONE_VFORK)) { 66521.106Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 66531.106Skamil PTRACE_VFORK); 66541.106Skamil } 66551.106Skamil 66561.106Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 66571.106Skamil 66581.106Skamil DPRINTF("Before resuming the forkee process where it left off " 66591.106Skamil "and without signal to be sent\n"); 66601.106Skamil SYSCALL_REQUIRE( 66611.106Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 66621.106Skamil 66631.106Skamil DPRINTF("Before resuming the child process where it left off " 66641.106Skamil "and without signal to be sent\n"); 66651.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66661.106Skamil } 66671.106Skamil#endif 66681.106Skamil 66691.106Skamil if (trackvforkdone && (flags & CLONE_VFORK)) { 66701.106Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 66711.106Skamil child); 66721.106Skamil TWAIT_REQUIRE_SUCCESS( 66731.106Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 66741.106Skamil 66751.106Skamil validate_status_stopped(status, SIGTRAP); 66761.106Skamil 66771.106Skamil SYSCALL_REQUIRE( 66781.106Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 66791.106Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 66801.106Skamil 66811.106Skamil child2 = state.pe_other_pid; 66821.106Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 66831.106Skamil child2); 66841.106Skamil 66851.106Skamil DPRINTF("Before resuming the child process where it left off " 66861.106Skamil "and without signal to be sent\n"); 66871.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 66881.106Skamil } 66891.106Skamil 66901.103Skamil#if defined(TWAIT_HAVE_PID) 66911.106Skamil if ((trackfork && !(flags & CLONE_VFORK)) || 66921.106Skamil (trackvfork && (flags & CLONE_VFORK))) { 66931.106Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 66941.106Skamil "\n", TWAIT_FNAME); 66951.106Skamil TWAIT_REQUIRE_SUCCESS( 66961.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 66971.106Skamil 66981.106Skamil validate_status_exited(status, exitval2); 66991.106Skamil 67001.106Skamil DPRINTF("Before calling %s() for the forkee - expected no " 67011.106Skamil "process\n", TWAIT_FNAME); 67021.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 67031.106Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 67041.106Skamil } 67051.106Skamil#endif 67061.106Skamil 67071.106Skamil DPRINTF("Before calling %s() for the child - expected stopped " 67081.106Skamil "SIGCHLD\n", TWAIT_FNAME); 67091.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67101.106Skamil 67111.106Skamil validate_status_stopped(status, SIGCHLD); 67121.106Skamil 67131.106Skamil DPRINTF("Before resuming the child process where it left off and " 67141.106Skamil "without signal to be sent\n"); 67151.106Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 67161.106Skamil 67171.106Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 67181.106Skamil TWAIT_FNAME); 67191.106Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 67201.106Skamil 67211.106Skamil validate_status_exited(status, exitval); 67221.103Skamil 67231.106Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 67241.106Skamil TWAIT_FNAME); 67251.106Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 67261.106Skamil} 67271.103Skamil 67281.106Skamil#define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone) \ 67291.106SkamilATF_TC(name); \ 67301.106SkamilATF_TC_HEAD(name, tc) \ 67311.106Skamil{ \ 67321.106Skamil atf_tc_set_md_var(tc, "descr", "Verify clone(%s) " \ 67331.106Skamil "called with 0%s%s%s in EVENT_MASK", \ 67341.106Skamil #flags, \ 67351.106Skamil tfork ? "|PTRACE_FORK" : "", \ 67361.106Skamil tvfork ? "|PTRACE_VFORK" : "", \ 67371.106Skamil tvforkdone ? "|PTRACE_VFORK_DONE" : ""); \ 67381.106Skamil} \ 67391.106Skamil \ 67401.106SkamilATF_TC_BODY(name, tc) \ 67411.106Skamil{ \ 67421.106Skamil \ 67431.106Skamil clone_body(flags, tfork, tvfork, tvforkdone); \ 67441.103Skamil} 67451.103Skamil 67461.106SkamilCLONE_TEST(clone1, 0, false, false, false) 67471.106Skamil#if defined(TWAIT_HAVE_PID) 67481.106SkamilCLONE_TEST(clone2, 0, true, false, false) 67491.106SkamilCLONE_TEST(clone3, 0, false, true, false) 67501.106SkamilCLONE_TEST(clone4, 0, true, true, false) 67511.106Skamil#endif 67521.106SkamilCLONE_TEST(clone5, 0, false, false, true) 67531.106Skamil#if defined(TWAIT_HAVE_PID) 67541.106SkamilCLONE_TEST(clone6, 0, true, false, true) 67551.106SkamilCLONE_TEST(clone7, 0, false, true, true) 67561.106SkamilCLONE_TEST(clone8, 0, true, true, true) 67571.106Skamil#endif 67581.106Skamil 67591.106SkamilCLONE_TEST(clone_vm1, CLONE_VM, false, false, false) 67601.106Skamil#if defined(TWAIT_HAVE_PID) 67611.106SkamilCLONE_TEST(clone_vm2, CLONE_VM, true, false, false) 67621.106SkamilCLONE_TEST(clone_vm3, CLONE_VM, false, true, false) 67631.106SkamilCLONE_TEST(clone_vm4, CLONE_VM, true, true, false) 67641.106Skamil#endif 67651.106SkamilCLONE_TEST(clone_vm5, CLONE_VM, false, false, true) 67661.106Skamil#if defined(TWAIT_HAVE_PID) 67671.106SkamilCLONE_TEST(clone_vm6, CLONE_VM, true, false, true) 67681.106SkamilCLONE_TEST(clone_vm7, CLONE_VM, false, true, true) 67691.106SkamilCLONE_TEST(clone_vm8, CLONE_VM, true, true, true) 67701.106Skamil#endif 67711.106Skamil 67721.106SkamilCLONE_TEST(clone_fs1, CLONE_FS, false, false, false) 67731.106Skamil#if defined(TWAIT_HAVE_PID) 67741.106SkamilCLONE_TEST(clone_fs2, CLONE_FS, true, false, false) 67751.106SkamilCLONE_TEST(clone_fs3, CLONE_FS, false, true, false) 67761.106SkamilCLONE_TEST(clone_fs4, CLONE_FS, true, true, false) 67771.106Skamil#endif 67781.106SkamilCLONE_TEST(clone_fs5, CLONE_FS, false, false, true) 67791.106Skamil#if defined(TWAIT_HAVE_PID) 67801.106SkamilCLONE_TEST(clone_fs6, CLONE_FS, true, false, true) 67811.106SkamilCLONE_TEST(clone_fs7, CLONE_FS, false, true, true) 67821.106SkamilCLONE_TEST(clone_fs8, CLONE_FS, true, true, true) 67831.106Skamil#endif 67841.106Skamil 67851.106SkamilCLONE_TEST(clone_files1, CLONE_FILES, false, false, false) 67861.106Skamil#if defined(TWAIT_HAVE_PID) 67871.106SkamilCLONE_TEST(clone_files2, CLONE_FILES, true, false, false) 67881.106SkamilCLONE_TEST(clone_files3, CLONE_FILES, false, true, false) 67891.106SkamilCLONE_TEST(clone_files4, CLONE_FILES, true, true, false) 67901.106Skamil#endif 67911.106SkamilCLONE_TEST(clone_files5, CLONE_FILES, false, false, true) 67921.106Skamil#if defined(TWAIT_HAVE_PID) 67931.106SkamilCLONE_TEST(clone_files6, CLONE_FILES, true, false, true) 67941.106SkamilCLONE_TEST(clone_files7, CLONE_FILES, false, true, true) 67951.106SkamilCLONE_TEST(clone_files8, CLONE_FILES, true, true, true) 67961.106Skamil#endif 67971.106Skamil 67981.106Skamil//CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false) 67991.106Skamil#if defined(TWAIT_HAVE_PID) 68001.106Skamil//CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false) 68011.106Skamil//CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false) 68021.106Skamil//CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false) 68031.106Skamil#endif 68041.106Skamil//CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true) 68051.106Skamil#if defined(TWAIT_HAVE_PID) 68061.106Skamil//CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true) 68071.106Skamil//CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true) 68081.106Skamil//CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true) 68091.106Skamil#endif 68101.106Skamil 68111.110Skamil#if TEST_VFORK_ENABLED 68121.106SkamilCLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false) 68131.106Skamil#if defined(TWAIT_HAVE_PID) 68141.106SkamilCLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false) 68151.106SkamilCLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false) 68161.106SkamilCLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false) 68171.106Skamil#endif 68181.106SkamilCLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true) 68191.106Skamil#if defined(TWAIT_HAVE_PID) 68201.106SkamilCLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true) 68211.106SkamilCLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true) 68221.106SkamilCLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true) 68231.106Skamil#endif 68241.110Skamil#endif 68251.106Skamil 68261.106Skamil/// ---------------------------------------------------------------------------- 68271.106Skamil 68281.106Skamil#if defined(TWAIT_HAVE_PID) 68291.103Skamilstatic void 68301.106Skamilclone_body2(int flags, bool masked, bool ignored) 68311.103Skamil{ 68321.103Skamil const int exitval = 5; 68331.103Skamil const int exitval2 = 15; 68341.103Skamil const int sigval = SIGSTOP; 68351.103Skamil pid_t child, child2 = 0, wpid; 68361.103Skamil#if defined(TWAIT_HAVE_STATUS) 68371.103Skamil int status; 68381.103Skamil#endif 68391.103Skamil ptrace_state_t state; 68401.103Skamil const int slen = sizeof(state); 68411.103Skamil ptrace_event_t event; 68421.103Skamil const int elen = sizeof(event); 68431.103Skamil struct sigaction sa; 68441.103Skamil struct ptrace_siginfo info; 68451.103Skamil sigset_t intmask; 68461.103Skamil struct kinfo_proc2 kp; 68471.103Skamil size_t len = sizeof(kp); 68481.103Skamil 68491.103Skamil int name[6]; 68501.103Skamil const size_t namelen = __arraycount(name); 68511.103Skamil ki_sigset_t kp_sigmask; 68521.103Skamil ki_sigset_t kp_sigignore; 68531.103Skamil 68541.103Skamil const size_t stack_size = 1024 * 1024; 68551.103Skamil void *stack, *stack_base; 68561.103Skamil 68571.103Skamil stack = malloc(stack_size); 68581.103Skamil ATF_REQUIRE(stack != NULL); 68591.103Skamil 68601.103Skamil#ifdef __MACHINE_STACK_GROWS_UP 68611.103Skamil stack_base = stack; 68621.103Skamil#else 68631.103Skamil stack_base = (char *)stack + stack_size; 68641.103Skamil#endif 68651.103Skamil 68661.103Skamil SYSCALL_REQUIRE((child = fork()) != -1); 68671.103Skamil if (child == 0) { 68681.103Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 68691.103Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 68701.103Skamil 68711.103Skamil if (masked) { 68721.103Skamil sigemptyset(&intmask); 68731.103Skamil sigaddset(&intmask, SIGTRAP); 68741.103Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 68751.103Skamil } 68761.103Skamil 68771.103Skamil if (ignored) { 68781.103Skamil memset(&sa, 0, sizeof(sa)); 68791.103Skamil sa.sa_handler = SIG_IGN; 68801.103Skamil sigemptyset(&sa.sa_mask); 68811.103Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 68821.103Skamil } 68831.103Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 68841.103Skamil FORKEE_ASSERT(raise(sigval) == 0); 68851.103Skamil 68861.103Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 68871.103Skamil flags); 68881.103Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 68891.103Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 68901.103Skamil 68911.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 68921.103Skamil child2); 68931.103Skamil 68941.103Skamil // XXX WALLSIG? 68951.103Skamil FORKEE_REQUIRE_SUCCESS 68961.103Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 68971.103Skamil 68981.103Skamil forkee_status_exited(status, exitval2); 68991.103Skamil 69001.103Skamil DPRINTF("Before exiting of the child process\n"); 69011.103Skamil _exit(exitval); 69021.103Skamil } 69031.103Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 69041.103Skamil 69051.103Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 69061.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 69071.103Skamil 69081.103Skamil validate_status_stopped(status, sigval); 69091.103Skamil 69101.103Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 69111.103Skamil SYSCALL_REQUIRE( 69121.103Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 69131.103Skamil 69141.103Skamil DPRINTF("Before checking siginfo_t\n"); 69151.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 69161.103Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 69171.103Skamil 69181.103Skamil name[0] = CTL_KERN, 69191.103Skamil name[1] = KERN_PROC2, 69201.103Skamil name[2] = KERN_PROC_PID; 69211.103Skamil name[3] = child; 69221.103Skamil name[4] = sizeof(kp); 69231.103Skamil name[5] = 1; 69241.103Skamil 69251.103Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 69261.103Skamil 69271.103Skamil if (masked) 69281.103Skamil kp_sigmask = kp.p_sigmask; 69291.103Skamil 69301.103Skamil if (ignored) 69311.103Skamil kp_sigignore = kp.p_sigignore; 69321.103Skamil 69331.103Skamil DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in " 69341.103Skamil "EVENT_MASK for the child %d\n", child); 69351.103Skamil event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE; 69361.103Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 69371.103Skamil 69381.103Skamil DPRINTF("Before resuming the child process where it left off and " 69391.103Skamil "without signal to be sent\n"); 69401.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 69411.103Skamil 69421.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 69431.103Skamil child); 69441.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 69451.103Skamil child); 69461.103Skamil 69471.103Skamil validate_status_stopped(status, SIGTRAP); 69481.103Skamil 69491.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 69501.103Skamil 69511.103Skamil if (masked) { 69521.103Skamil DPRINTF("kp_sigmask=" 69531.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 69541.103Skamil PRIx32 "\n", 69551.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 69561.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 69571.103Skamil 69581.103Skamil DPRINTF("kp.p_sigmask=" 69591.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 69601.103Skamil PRIx32 "\n", 69611.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 69621.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 69631.103Skamil 69641.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 69651.103Skamil sizeof(kp_sigmask))); 69661.103Skamil } 69671.103Skamil 69681.103Skamil if (ignored) { 69691.103Skamil DPRINTF("kp_sigignore=" 69701.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 69711.103Skamil PRIx32 "\n", 69721.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 69731.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 69741.103Skamil 69751.103Skamil DPRINTF("kp.p_sigignore=" 69761.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 69771.103Skamil PRIx32 "\n", 69781.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 69791.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 69801.103Skamil 69811.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 69821.103Skamil sizeof(kp_sigignore))); 69831.103Skamil } 69841.103Skamil 69851.103Skamil SYSCALL_REQUIRE( 69861.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 69871.103Skamil DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event, 69881.103Skamil child2); 69891.103Skamil if (!(flags & CLONE_VFORK)) { 69901.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 69911.103Skamil PTRACE_FORK); 69921.103Skamil } else { 69931.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 69941.103Skamil PTRACE_VFORK); 69951.103Skamil } 69961.103Skamil 69971.103Skamil child2 = state.pe_other_pid; 69981.103Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 69991.103Skamil 70001.103Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 70011.103Skamil "%d\n", TWAIT_FNAME, child2, child); 70021.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 70031.103Skamil child2); 70041.103Skamil 70051.103Skamil validate_status_stopped(status, SIGTRAP); 70061.103Skamil 70071.103Skamil name[3] = child2; 70081.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 70091.103Skamil 70101.103Skamil if (masked) { 70111.103Skamil DPRINTF("kp_sigmask=" 70121.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 70131.103Skamil PRIx32 "\n", 70141.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 70151.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 70161.103Skamil 70171.103Skamil DPRINTF("kp.p_sigmask=" 70181.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 70191.103Skamil PRIx32 "\n", 70201.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 70211.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 70221.103Skamil 70231.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 70241.103Skamil sizeof(kp_sigmask))); 70251.103Skamil } 70261.103Skamil 70271.103Skamil if (ignored) { 70281.103Skamil DPRINTF("kp_sigignore=" 70291.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 70301.103Skamil PRIx32 "\n", 70311.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 70321.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 70331.103Skamil 70341.103Skamil DPRINTF("kp.p_sigignore=" 70351.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 70361.103Skamil PRIx32 "\n", 70371.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 70381.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 70391.103Skamil 70401.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 70411.103Skamil sizeof(kp_sigignore))); 70421.103Skamil } 70431.103Skamil 70441.103Skamil SYSCALL_REQUIRE( 70451.103Skamil ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 70461.103Skamil if (!(flags & CLONE_VFORK)) { 70471.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 70481.103Skamil PTRACE_FORK); 70491.103Skamil } else { 70501.103Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 70511.103Skamil PTRACE_VFORK); 70521.103Skamil } 70531.103Skamil 70541.103Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 70551.103Skamil 70561.103Skamil DPRINTF("Before resuming the forkee process where it left off " 70571.103Skamil "and without signal to be sent\n"); 70581.103Skamil SYSCALL_REQUIRE( 70591.103Skamil ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 70601.103Skamil 70611.103Skamil DPRINTF("Before resuming the child process where it left off " 70621.103Skamil "and without signal to be sent\n"); 70631.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 70641.103Skamil 70651.103Skamil if (flags & CLONE_VFORK) { 70661.103Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 70671.103Skamil child); 70681.103Skamil TWAIT_REQUIRE_SUCCESS( 70691.103Skamil wpid = TWAIT_GENERIC(child, &status, 0), child); 70701.103Skamil 70711.103Skamil validate_status_stopped(status, SIGTRAP); 70721.103Skamil 70731.103Skamil name[3] = child; 70741.103Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 70751.103Skamil 70761.103Skamil /* 70771.103Skamil * SIGCHLD is now pending in the signal queue and 70781.103Skamil * the kernel presents it to userland as a masked signal. 70791.103Skamil */ 70801.103Skamil sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD); 70811.103Skamil 70821.103Skamil if (masked) { 70831.103Skamil DPRINTF("kp_sigmask=" 70841.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 70851.103Skamil PRIx32 "\n", 70861.103Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 70871.103Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 70881.103Skamil 70891.103Skamil DPRINTF("kp.p_sigmask=" 70901.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 70911.103Skamil PRIx32 "\n", 70921.103Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 70931.103Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 70941.103Skamil 70951.103Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 70961.103Skamil sizeof(kp_sigmask))); 70971.103Skamil } 70981.103Skamil 70991.103Skamil if (ignored) { 71001.103Skamil DPRINTF("kp_sigignore=" 71011.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71021.103Skamil PRIx32 "\n", 71031.103Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 71041.103Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 71051.103Skamil 71061.103Skamil DPRINTF("kp.p_sigignore=" 71071.103Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 71081.103Skamil PRIx32 "\n", 71091.103Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 71101.103Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 71111.103Skamil 71121.103Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 71131.103Skamil sizeof(kp_sigignore))); 71141.103Skamil } 71151.103Skamil 71161.103Skamil SYSCALL_REQUIRE( 71171.103Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 71181.103Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 71191.103Skamil 71201.103Skamil child2 = state.pe_other_pid; 71211.103Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 71221.103Skamil child2); 71231.103Skamil 71241.103Skamil DPRINTF("Before resuming the child process where it left off " 71251.103Skamil "and without signal to be sent\n"); 71261.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 71271.103Skamil } 71281.103Skamil 71291.103Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 71301.103Skamil "\n", TWAIT_FNAME); 71311.103Skamil TWAIT_REQUIRE_SUCCESS( 71321.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0), child2); 71331.103Skamil 71341.103Skamil validate_status_exited(status, exitval2); 71351.103Skamil 71361.103Skamil DPRINTF("Before calling %s() for the forkee - expected no " 71371.103Skamil "process\n", TWAIT_FNAME); 71381.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 71391.103Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 71401.103Skamil 71411.103Skamil DPRINTF("Before calling %s() for the child - expected stopped " 71421.103Skamil "SIGCHLD\n", TWAIT_FNAME); 71431.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 71441.103Skamil 71451.103Skamil validate_status_stopped(status, SIGCHLD); 71461.103Skamil 71471.103Skamil DPRINTF("Before resuming the child process where it left off and " 71481.103Skamil "without signal to be sent\n"); 71491.103Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 71501.103Skamil 71511.103Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 71521.103Skamil TWAIT_FNAME); 71531.103Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 71541.103Skamil 71551.103Skamil validate_status_exited(status, exitval); 71561.103Skamil 71571.103Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 71581.103Skamil TWAIT_FNAME); 71591.103Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 71601.103Skamil} 71611.103Skamil 71621.106Skamil#define CLONE_TEST2(name,flags,masked,ignored) \ 71631.103SkamilATF_TC(name); \ 71641.103SkamilATF_TC_HEAD(name, tc) \ 71651.103Skamil{ \ 71661.103Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\ 71671.103Skamil " regardless of signal %s%s", \ 71681.103Skamil #flags, masked ? "masked" : "", ignored ? "ignored" : ""); \ 71691.103Skamil} \ 71701.103Skamil \ 71711.103SkamilATF_TC_BODY(name, tc) \ 71721.103Skamil{ \ 71731.103Skamil \ 71741.106Skamil clone_body2(flags, masked, ignored); \ 71751.103Skamil} 71761.103Skamil 71771.106SkamilCLONE_TEST2(clone_signalignored, 0, true, false) 71781.106SkamilCLONE_TEST2(clone_signalmasked, 0, false, true) 71791.106SkamilCLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false) 71801.106SkamilCLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true) 71811.106SkamilCLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false) 71821.106SkamilCLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true) 71831.106SkamilCLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false) 71841.106SkamilCLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true) 71851.106Skamil//CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX 71861.106Skamil//CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true) // XXX 71871.110Skamil#if TEST_VFORK_ENABLED 71881.106SkamilCLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false) 71891.106SkamilCLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true) 71901.103Skamil#endif 71911.110Skamil#endif 71921.103Skamil 71931.103Skamil/// ---------------------------------------------------------------------------- 71941.103Skamil 71951.111Skamil#if TEST_VFORK_ENABLED 71961.107Skamil#if defined(TWAIT_HAVE_PID) 71971.107Skamilstatic void 71981.107Skamiltraceme_vfork_clone_body(int flags) 71991.107Skamil{ 72001.107Skamil const int exitval = 5; 72011.107Skamil const int exitval2 = 15; 72021.107Skamil pid_t child, child2 = 0, wpid; 72031.107Skamil#if defined(TWAIT_HAVE_STATUS) 72041.107Skamil int status; 72051.107Skamil#endif 72061.107Skamil 72071.107Skamil const size_t stack_size = 1024 * 1024; 72081.107Skamil void *stack, *stack_base; 72091.107Skamil 72101.107Skamil stack = malloc(stack_size); 72111.107Skamil ATF_REQUIRE(stack != NULL); 72121.107Skamil 72131.107Skamil#ifdef __MACHINE_STACK_GROWS_UP 72141.107Skamil stack_base = stack; 72151.107Skamil#else 72161.107Skamil stack_base = (char *)stack + stack_size; 72171.107Skamil#endif 72181.107Skamil 72191.107Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 72201.107Skamil if (child == 0) { 72211.107Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 72221.107Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 72231.107Skamil 72241.107Skamil DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(), 72251.107Skamil flags); 72261.107Skamil SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base, 72271.107Skamil flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1); 72281.107Skamil 72291.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), 72301.107Skamil child2); 72311.107Skamil 72321.107Skamil // XXX WALLSIG? 72331.107Skamil FORKEE_REQUIRE_SUCCESS 72341.107Skamil (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2); 72351.107Skamil 72361.107Skamil forkee_status_exited(status, exitval2); 72371.107Skamil 72381.107Skamil DPRINTF("Before exiting of the child process\n"); 72391.107Skamil _exit(exitval); 72401.107Skamil } 72411.107Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 72421.107Skamil 72431.107Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 72441.107Skamil TWAIT_FNAME); 72451.107Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 72461.107Skamil 72471.107Skamil validate_status_exited(status, exitval); 72481.107Skamil 72491.107Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 72501.107Skamil TWAIT_FNAME); 72511.107Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 72521.107Skamil} 72531.107Skamil 72541.107Skamil#define TRACEME_VFORK_CLONE_TEST(name,flags) \ 72551.107SkamilATF_TC(name); \ 72561.107SkamilATF_TC_HEAD(name, tc) \ 72571.107Skamil{ \ 72581.107Skamil atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is " \ 72591.107Skamil "handled correctly with vfork(2)ed tracer", \ 72601.107Skamil #flags); \ 72611.107Skamil} \ 72621.107Skamil \ 72631.107SkamilATF_TC_BODY(name, tc) \ 72641.107Skamil{ \ 72651.107Skamil \ 72661.107Skamil traceme_vfork_clone_body(flags); \ 72671.107Skamil} 72681.107Skamil 72691.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0) 72701.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM) 72711.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS) 72721.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES) 72731.107Skamil//TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND) // XXX 72741.107SkamilTRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK) 72751.107Skamil#endif 72761.110Skamil#endif 72771.107Skamil 72781.107Skamil/// ---------------------------------------------------------------------------- 72791.107Skamil 72801.1Skamil#include "t_ptrace_amd64_wait.h" 72811.1Skamil#include "t_ptrace_i386_wait.h" 72821.1Skamil#include "t_ptrace_x86_wait.h" 72831.1Skamil 72841.1SkamilATF_TP_ADD_TCS(tp) 72851.1Skamil{ 72861.1Skamil setvbuf(stdout, NULL, _IONBF, 0); 72871.1Skamil setvbuf(stderr, NULL, _IONBF, 0); 72881.33Skamil 72891.36Skamil ATF_TP_ADD_TC(tp, traceme_raise1); 72901.33Skamil ATF_TP_ADD_TC(tp, traceme_raise2); 72911.33Skamil ATF_TP_ADD_TC(tp, traceme_raise3); 72921.33Skamil ATF_TP_ADD_TC(tp, traceme_raise4); 72931.33Skamil ATF_TP_ADD_TC(tp, traceme_raise5); 72941.85Skamil ATF_TP_ADD_TC(tp, traceme_raise6); 72951.85Skamil ATF_TP_ADD_TC(tp, traceme_raise7); 72961.85Skamil ATF_TP_ADD_TC(tp, traceme_raise8); 72971.85Skamil ATF_TP_ADD_TC(tp, traceme_raise9); 72981.85Skamil ATF_TP_ADD_TC(tp, traceme_raise10); 72991.33Skamil 73001.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1); 73011.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2); 73021.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3); 73031.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4); 73041.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5); 73051.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6); 73061.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7); 73071.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8); 73081.87Skamil 73091.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1); 73101.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2); 73111.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3); 73121.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4); 73131.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5); 73141.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6); 73151.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7); 73161.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8); 73171.86Skamil 73181.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_trap); 73191.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_segv); 73201.71Skamil ATF_TP_ADD_TC(tp, traceme_crash_ill); 73211.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_fpe); 73221.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_bus); 73231.59Skamil 73241.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap); 73251.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv); 73261.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill); 73271.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe); 73281.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus); 73291.88Skamil 73301.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap); 73311.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv); 73321.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill); 73331.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe); 73341.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus); 73351.88Skamil 73361.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1); 73371.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2); 73381.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3); 73391.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4); 73401.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5); 73411.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6); 73421.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7); 73431.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8); 73441.50Skamil 73451.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1); 73461.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2); 73471.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3); 73481.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4); 73491.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5); 73501.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6); 73511.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7); 73521.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8); 73531.50Skamil 73541.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1); 73551.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2); 73561.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3); 73571.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4); 73581.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5); 73591.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6); 73601.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7); 73611.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8); 73621.50Skamil 73631.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1); 73641.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2); 73651.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3); 73661.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4); 73671.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5); 73681.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6); 73691.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7); 73701.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8); 73711.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9); 73721.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10); 73731.1Skamil 73741.37Skamil ATF_TP_ADD_TC(tp, traceme_pid1_parent); 73751.37Skamil 73761.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise1); 73771.46Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise2); 73781.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise3); 73791.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise4); 73801.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise5); 73811.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise6); 73821.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise7); 73831.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise8); 73841.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise9); 73851.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise10); 73861.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise11); 73871.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise12); 73881.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise13); 73891.40Skamil 73901.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap); 73911.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv); 73921.71Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill); 73931.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe); 73941.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus); 73951.41Skamil 73961.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap); 73971.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv); 73981.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill); 73991.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe); 74001.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus); 74011.92Skamil 74021.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap); 74031.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv); 74041.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill); 74051.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe); 74061.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus); 74071.92Skamil 74081.43Skamil ATF_TP_ADD_TC(tp, traceme_vfork_exec); 74091.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec); 74101.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec); 74111.43Skamil 74121.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap); 74131.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv); 74141.71Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill); 74151.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe); 74161.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus); 74171.59Skamil 74181.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 74191.94Skamil unrelated_tracer_sees_signalmasked_crash_trap); 74201.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 74211.94Skamil unrelated_tracer_sees_signalmasked_crash_segv); 74221.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 74231.94Skamil unrelated_tracer_sees_signalmasked_crash_ill); 74241.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 74251.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe); 74261.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 74271.94Skamil unrelated_tracer_sees_signalmasked_crash_bus); 74281.94Skamil 74291.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 74301.94Skamil unrelated_tracer_sees_signalignored_crash_trap); 74311.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 74321.94Skamil unrelated_tracer_sees_signalignored_crash_segv); 74331.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 74341.94Skamil unrelated_tracer_sees_signalignored_crash_ill); 74351.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 74361.94Skamil unrelated_tracer_sees_signalignored_crash_fpe); 74371.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 74381.94Skamil unrelated_tracer_sees_signalignored_crash_bus); 74391.94Skamil 74401.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent); 74411.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates); 74421.61Skre ATF_TP_ADD_TC_HAVE_PID(tp, 74431.61Skre unrelated_tracer_sees_terminaton_before_the_parent); 74441.67Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process); 74451.51Skamil 74461.51Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_child); 74471.66Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child); 74481.51Skamil 74491.51Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_parent); 74501.65Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent); 74511.51Skamil 74521.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 74531.51Skamil tracee_sees_its_original_parent_getppid); 74541.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 74551.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2); 74561.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 74571.51Skamil tracee_sees_its_original_parent_procfs_status); 74581.1Skamil 74591.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_empty); 74601.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_fork); 74611.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork); 74621.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done); 74631.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create); 74641.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit); 74651.1Skamil 74661.31Skamil ATF_TP_ADD_TC(tp, fork1); 74671.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork2); 74681.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork3); 74691.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork4); 74701.31Skamil ATF_TP_ADD_TC(tp, fork5); 74711.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork6); 74721.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork7); 74731.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork8); 74741.31Skamil 74751.109Skamil#if TEST_VFORK_ENABLED 74761.31Skamil ATF_TP_ADD_TC(tp, vfork1); 74771.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork2); 74781.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork3); 74791.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork4); 74801.31Skamil ATF_TP_ADD_TC(tp, vfork5); 74811.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork6); 74821.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork7); 74831.104Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork8); 74841.1Skamil 74851.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_fork); 74861.108Skamil ATF_TP_ADD_TC(tp, traceme_vfork_vfork); 74871.109Skamil#endif 74881.108Skamil 74891.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8); 74901.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16); 74911.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32); 74921.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64); 74931.54Skamil 74941.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8); 74951.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16); 74961.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32); 74971.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64); 74981.54Skamil 74991.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8); 75001.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16); 75011.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32); 75021.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64); 75031.54Skamil 75041.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8); 75051.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16); 75061.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32); 75071.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64); 75081.54Skamil 75091.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d); 75101.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i); 75111.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d); 75121.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i); 75131.54Skamil 75141.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text); 75151.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text); 75161.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text); 75171.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text); 75181.54Skamil 75191.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text); 75201.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text); 75211.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text); 75221.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text); 75231.54Skamil 75241.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text); 75251.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text); 75261.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text); 75271.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text); 75281.54Skamil 75291.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text); 75301.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text); 75311.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text); 75321.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text); 75331.54Skamil 75341.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text); 75351.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text); 75361.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text); 75371.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text); 75381.1Skamil 75391.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv); 75401.1Skamil 75411.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i); 75421.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d); 75431.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i); 75441.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d); 75451.101Skamil 75461.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i); 75471.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d); 75481.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i); 75491.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d); 75501.101Skamil 75511.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv); 75521.101Skamil 75531.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i); 75541.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d); 75551.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i); 75561.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d); 75571.115Skamil 75581.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i); 75591.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d); 75601.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i); 75611.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d); 75621.115Skamil 75631.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1); 75641.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2); 75651.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3); 75661.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4); 75671.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5); 75681.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6); 75691.1Skamil 75701.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1); 75711.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2); 75721.1Skamil 75731.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step1); 75741.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step2); 75751.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step3); 75761.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step4); 75771.1Skamil 75781.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep1); 75791.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep2); 75801.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep3); 75811.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep4); 75821.2Skamil 75831.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked); 75841.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored); 75851.95Skamil 75861.1Skamil ATF_TP_ADD_TC(tp, kill1); 75871.1Skamil ATF_TP_ADD_TC(tp, kill2); 75881.75Skamil ATF_TP_ADD_TC(tp, kill3); 75891.1Skamil 75901.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0); 75911.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1); 75921.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2); 75931.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3); 75941.77Skamil 75951.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0); 75961.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1); 75971.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2); 75981.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3); 75991.1Skamil 76001.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_unmodified); 76011.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_faked); 76021.79Skamil 76031.82Skamil ATF_TP_ADD_TC(tp, traceme_exec); 76041.97Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_exec); 76051.97Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_exec); 76061.1Skamil 76071.83Skamil ATF_TP_ADD_TC(tp, trace_thread1); 76081.83Skamil ATF_TP_ADD_TC(tp, trace_thread2); 76091.83Skamil ATF_TP_ADD_TC(tp, trace_thread3); 76101.83Skamil ATF_TP_ADD_TC(tp, trace_thread4); 76111.1Skamil 76121.84Skamil ATF_TP_ADD_TC(tp, signal_mask_unrelated); 76131.84Skamil 76141.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalmasked); 76151.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork_singalignored); 76161.109Skamil#if TEST_VFORK_ENABLED 76171.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalmasked); 76181.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork_singalignored); 76191.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalmasked); 76201.99Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vforkdone_singalignored); 76211.109Skamil#endif 76221.99Skamil 76231.1Skamil ATF_TP_ADD_TC(tp, signal9); 76241.1Skamil ATF_TP_ADD_TC(tp, signal10); 76251.1Skamil 76261.1Skamil ATF_TP_ADD_TC(tp, suspend1); 76271.1Skamil ATF_TP_ADD_TC(tp, suspend2); 76281.1Skamil 76291.1Skamil ATF_TP_ADD_TC(tp, resume1); 76301.1Skamil 76311.1Skamil ATF_TP_ADD_TC(tp, syscall1); 76321.1Skamil 76331.1Skamil ATF_TP_ADD_TC(tp, syscallemu1); 76341.1Skamil 76351.106Skamil ATF_TP_ADD_TC(tp, clone1); 76361.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone2); 76371.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone3); 76381.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone4); 76391.106Skamil ATF_TP_ADD_TC(tp, clone5); 76401.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone6); 76411.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone7); 76421.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone8); 76431.106Skamil 76441.106Skamil ATF_TP_ADD_TC(tp, clone_vm1); 76451.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2); 76461.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3); 76471.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4); 76481.106Skamil ATF_TP_ADD_TC(tp, clone_vm5); 76491.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6); 76501.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7); 76511.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8); 76521.106Skamil 76531.106Skamil ATF_TP_ADD_TC(tp, clone_fs1); 76541.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2); 76551.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3); 76561.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4); 76571.106Skamil ATF_TP_ADD_TC(tp, clone_fs5); 76581.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6); 76591.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7); 76601.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8); 76611.106Skamil 76621.106Skamil ATF_TP_ADD_TC(tp, clone_files1); 76631.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2); 76641.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3); 76651.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4); 76661.106Skamil ATF_TP_ADD_TC(tp, clone_files5); 76671.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6); 76681.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7); 76691.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8); 76701.106Skamil 76711.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand1); // XXX 76721.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX 76731.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX 76741.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX 76751.106Skamil// ATF_TP_ADD_TC(tp, clone_sighand5); // XXX 76761.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX 76771.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX 76781.106Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX 76791.106Skamil 76801.109Skamil#if TEST_VFORK_ENABLED 76811.106Skamil ATF_TP_ADD_TC(tp, clone_vfork1); 76821.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2); 76831.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3); 76841.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4); 76851.106Skamil ATF_TP_ADD_TC(tp, clone_vfork5); 76861.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6); 76871.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7); 76881.106Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8); 76891.109Skamil#endif 76901.106Skamil 76911.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored); 76921.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked); 76931.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored); 76941.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked); 76951.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored); 76961.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked); 76971.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored); 76981.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked); 76991.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX 77001.103Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX 77011.109Skamil#if TEST_VFORK_ENABLED 77021.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored); 77031.103Skamil ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked); 77041.109Skamil#endif 77051.103Skamil 77061.109Skamil#if TEST_VFORK_ENABLED 77071.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone); 77081.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm); 77091.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs); 77101.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files); 77111.107Skamil// ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX 77121.107Skamil ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork); 77131.109Skamil#endif 77141.107Skamil 77151.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64(); 77161.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_I386(); 77171.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_X86(); 77181.1Skamil 77191.1Skamil return atf_no_error(); 77201.1Skamil} 7721