t_ptrace_wait.c revision 1.95
11.95Skamil/* $NetBSD: t_ptrace_wait.c,v 1.95 2019/02/20 09:25:11 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.95Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.95 2019/02/20 09:25:11 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.1Skamil#include <atf-c.h> 571.1Skamil 581.1Skamil#include "h_macros.h" 591.1Skamil 601.1Skamil#include "t_ptrace_wait.h" 611.1Skamil#include "msg.h" 621.1Skamil 631.1Skamil#define PARENT_TO_CHILD(info, fds, msg) \ 641.61Skre SYSCALL_REQUIRE(msg_write_child(info " to child " # fds, &fds, &msg, \ 651.61Skre sizeof(msg)) == 0) 661.1Skamil 671.1Skamil#define CHILD_FROM_PARENT(info, fds, msg) \ 681.61Skre FORKEE_ASSERT(msg_read_parent(info " from parent " # fds, &fds, &msg, \ 691.61Skre sizeof(msg)) == 0) 701.1Skamil 711.1Skamil#define CHILD_TO_PARENT(info, fds, msg) \ 721.61Skre FORKEE_ASSERT(msg_write_parent(info " to parent " # fds, &fds, &msg, \ 731.61Skre sizeof(msg)) == 0) 741.1Skamil 751.1Skamil#define PARENT_FROM_CHILD(info, fds, msg) \ 761.61Skre SYSCALL_REQUIRE(msg_read_child(info " from parent " # fds, &fds, &msg, \ 771.61Skre sizeof(msg)) == 0) 781.13Schristos 791.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \ 801.13Schristos strerror(errno)) 811.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \ 821.18Schristos "%d(%s) != %d", res, strerror(res), exp) 831.13Schristos 841.13Schristosstatic int debug = 0; 851.13Schristos 861.13Schristos#define DPRINTF(a, ...) do \ 871.13Schristos if (debug) printf(a, ##__VA_ARGS__); \ 881.13Schristos while (/*CONSTCOND*/0) 891.1Skamil 901.34Skamil/// ---------------------------------------------------------------------------- 911.34Skamil 921.33Skamilstatic void 931.33Skamiltraceme_raise(int sigval) 941.1Skamil{ 951.1Skamil const int exitval = 5; 961.1Skamil pid_t child, wpid; 971.1Skamil#if defined(TWAIT_HAVE_STATUS) 981.1Skamil int status; 991.1Skamil#endif 1001.1Skamil 1011.45Skamil struct ptrace_siginfo info; 1021.45Skamil memset(&info, 0, sizeof(info)); 1031.45Skamil 1041.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 1051.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 1061.1Skamil if (child == 0) { 1071.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1081.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1091.1Skamil 1101.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1111.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 1121.1Skamil 1131.36Skamil switch (sigval) { 1141.36Skamil case SIGKILL: 1151.36Skamil /* NOTREACHED */ 1161.36Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 1171.70Smrg __unreachable(); 1181.36Skamil default: 1191.36Skamil DPRINTF("Before exiting of the child process\n"); 1201.36Skamil _exit(exitval); 1211.36Skamil } 1221.1Skamil } 1231.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1241.1Skamil 1251.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1261.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1271.1Skamil 1281.36Skamil switch (sigval) { 1291.36Skamil case SIGKILL: 1301.36Skamil validate_status_signaled(status, sigval, 0); 1311.36Skamil break; 1321.36Skamil default: 1331.36Skamil validate_status_stopped(status, sigval); 1341.1Skamil 1351.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 1361.61Skre "child\n"); 1371.45Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 1381.61Skre sizeof(info)) != -1); 1391.45Skamil 1401.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1411.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 1421.61Skre "si_errno=%#x\n", 1431.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1441.61Skre info.psi_siginfo.si_errno); 1451.45Skamil 1461.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 1471.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 1481.45Skamil 1491.36Skamil DPRINTF("Before resuming the child process where it left off " 1501.36Skamil "and without signal to be sent\n"); 1511.36Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1521.1Skamil 1531.36Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1541.36Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 1551.61Skre child); 1561.36Skamil break; 1571.36Skamil } 1581.1Skamil 1591.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1601.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 1611.1Skamil} 1621.1Skamil 1631.61Skre#define TRACEME_RAISE(test, sig) \ 1641.61SkreATF_TC(test); \ 1651.61SkreATF_TC_HEAD(test, tc) \ 1661.61Skre{ \ 1671.61Skre atf_tc_set_md_var(tc, "descr", \ 1681.61Skre "Verify " #sig " followed by _exit(2) in a child"); \ 1691.61Skre} \ 1701.61Skre \ 1711.61SkreATF_TC_BODY(test, tc) \ 1721.61Skre{ \ 1731.61Skre \ 1741.61Skre traceme_raise(sig); \ 1751.33Skamil} 1761.33Skamil 1771.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */ 1781.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */ 1791.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */ 1801.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP) /* hangup */ 1811.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */ 1821.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */ 1831.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */ 1841.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */ 1851.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */ 1861.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */ 1871.33Skamil 1881.34Skamil/// ---------------------------------------------------------------------------- 1891.1Skamil 1901.1Skamilstatic void 1911.87Skamiltraceme_raisesignal_ignored(int sigignored) 1921.87Skamil{ 1931.87Skamil const int exitval = 5; 1941.87Skamil const int sigval = SIGSTOP; 1951.87Skamil pid_t child, wpid; 1961.87Skamil struct sigaction sa; 1971.87Skamil#if defined(TWAIT_HAVE_STATUS) 1981.87Skamil int status; 1991.87Skamil#endif 2001.87Skamil struct ptrace_siginfo info; 2011.87Skamil 2021.87Skamil memset(&info, 0, sizeof(info)); 2031.87Skamil 2041.87Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 2051.87Skamil SYSCALL_REQUIRE((child = fork()) != -1); 2061.87Skamil if (child == 0) { 2071.87Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2081.87Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2091.87Skamil 2101.87Skamil memset(&sa, 0, sizeof(sa)); 2111.87Skamil sa.sa_handler = SIG_IGN; 2121.87Skamil sigemptyset(&sa.sa_mask); 2131.87Skamil FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1); 2141.87Skamil 2151.87Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 2161.87Skamil FORKEE_ASSERT(raise(sigval) == 0); 2171.87Skamil 2181.87Skamil DPRINTF("Before raising %s from child\n", 2191.87Skamil strsignal(sigignored)); 2201.87Skamil FORKEE_ASSERT(raise(sigignored) == 0); 2211.87Skamil 2221.87Skamil DPRINTF("Before exiting of the child process\n"); 2231.87Skamil _exit(exitval); 2241.87Skamil } 2251.87Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2261.87Skamil 2271.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2281.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2291.87Skamil 2301.87Skamil validate_status_stopped(status, sigval); 2311.87Skamil 2321.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2331.87Skamil SYSCALL_REQUIRE( 2341.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2351.87Skamil 2361.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2371.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2381.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2391.87Skamil info.psi_siginfo.si_errno); 2401.87Skamil 2411.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 2421.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2431.87Skamil 2441.87Skamil DPRINTF("Before resuming the child process where it left off and " 2451.87Skamil "without signal to be sent\n"); 2461.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2471.87Skamil 2481.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2491.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2501.87Skamil 2511.87Skamil validate_status_stopped(status, sigignored); 2521.87Skamil 2531.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2541.87Skamil SYSCALL_REQUIRE( 2551.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2561.87Skamil 2571.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2581.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2591.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2601.87Skamil info.psi_siginfo.si_errno); 2611.87Skamil 2621.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored); 2631.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2641.87Skamil 2651.87Skamil DPRINTF("Before resuming the child process where it left off and " 2661.87Skamil "without signal to be sent\n"); 2671.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2681.87Skamil 2691.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2701.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2711.87Skamil 2721.87Skamil validate_status_exited(status, exitval); 2731.87Skamil 2741.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2751.87Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 2761.87Skamil} 2771.87Skamil 2781.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig) \ 2791.87SkamilATF_TC(test); \ 2801.87SkamilATF_TC_HEAD(test, tc) \ 2811.87Skamil{ \ 2821.87Skamil atf_tc_set_md_var(tc, "descr", \ 2831.87Skamil "Verify that ignoring (with SIG_IGN) " #sig " in tracee " \ 2841.87Skamil "does not stop tracer from catching this raised signal"); \ 2851.87Skamil} \ 2861.87Skamil \ 2871.87SkamilATF_TC_BODY(test, tc) \ 2881.87Skamil{ \ 2891.87Skamil \ 2901.87Skamil traceme_raisesignal_ignored(sig); \ 2911.87Skamil} 2921.87Skamil 2931.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 2941.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */ 2951.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP) /* hangup */ 2961.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */ 2971.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */ 2981.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */ 2991.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */ 3001.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */ 3011.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */ 3021.87Skamil 3031.87Skamil/// ---------------------------------------------------------------------------- 3041.87Skamil 3051.87Skamilstatic void 3061.86Skamiltraceme_raisesignal_masked(int sigmasked) 3071.86Skamil{ 3081.86Skamil const int exitval = 5; 3091.86Skamil const int sigval = SIGSTOP; 3101.86Skamil pid_t child, wpid; 3111.86Skamil#if defined(TWAIT_HAVE_STATUS) 3121.86Skamil int status; 3131.86Skamil#endif 3141.86Skamil sigset_t intmask; 3151.86Skamil struct ptrace_siginfo info; 3161.86Skamil 3171.86Skamil memset(&info, 0, sizeof(info)); 3181.86Skamil 3191.86Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 3201.86Skamil SYSCALL_REQUIRE((child = fork()) != -1); 3211.86Skamil if (child == 0) { 3221.86Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 3231.86Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 3241.86Skamil 3251.86Skamil sigemptyset(&intmask); 3261.86Skamil sigaddset(&intmask, sigmasked); 3271.86Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 3281.86Skamil 3291.86Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 3301.86Skamil FORKEE_ASSERT(raise(sigval) == 0); 3311.86Skamil 3321.86Skamil DPRINTF("Before raising %s breakpoint from child\n", 3331.86Skamil strsignal(sigmasked)); 3341.86Skamil FORKEE_ASSERT(raise(sigmasked) == 0); 3351.86Skamil 3361.86Skamil DPRINTF("Before exiting of the child process\n"); 3371.86Skamil _exit(exitval); 3381.86Skamil } 3391.86Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 3401.86Skamil 3411.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3421.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3431.86Skamil 3441.86Skamil validate_status_stopped(status, sigval); 3451.86Skamil 3461.86Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 3471.86Skamil SYSCALL_REQUIRE( 3481.86Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 3491.86Skamil 3501.86Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 3511.86Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 3521.86Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 3531.86Skamil info.psi_siginfo.si_errno); 3541.86Skamil 3551.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 3561.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 3571.86Skamil 3581.86Skamil DPRINTF("Before resuming the child process where it left off and " 3591.86Skamil "without signal to be sent\n"); 3601.86Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 3611.86Skamil 3621.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3631.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3641.86Skamil 3651.86Skamil validate_status_exited(status, exitval); 3661.86Skamil 3671.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3681.86Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 3691.86Skamil} 3701.86Skamil 3711.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig) \ 3721.86SkamilATF_TC(test); \ 3731.86SkamilATF_TC_HEAD(test, tc) \ 3741.86Skamil{ \ 3751.86Skamil atf_tc_set_md_var(tc, "descr", \ 3761.86Skamil "Verify that masking (with SIG_BLOCK) " #sig " in tracee " \ 3771.86Skamil "stops tracer from catching this raised signal"); \ 3781.86Skamil} \ 3791.86Skamil \ 3801.86SkamilATF_TC_BODY(test, tc) \ 3811.86Skamil{ \ 3821.86Skamil \ 3831.86Skamil traceme_raisesignal_masked(sig); \ 3841.86Skamil} 3851.86Skamil 3861.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 3871.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */ 3881.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP) /* hangup */ 3891.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */ 3901.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */ 3911.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */ 3921.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */ 3931.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */ 3941.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */ 3951.86Skamil 3961.86Skamil/// ---------------------------------------------------------------------------- 3971.86Skamil 3981.86Skamilstatic void 3991.59Skamiltraceme_crash(int sig) 4001.59Skamil{ 4011.59Skamil pid_t child, wpid; 4021.59Skamil#if defined(TWAIT_HAVE_STATUS) 4031.59Skamil int status; 4041.59Skamil#endif 4051.59Skamil struct ptrace_siginfo info; 4061.61Skre 4071.71Skamil#ifndef PTRACE_ILLEGAL_ASM 4081.71Skamil if (sig == SIGILL) 4091.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 4101.71Skamil#endif 4111.71Skamil 4121.59Skamil memset(&info, 0, sizeof(info)); 4131.59Skamil 4141.59Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 4151.59Skamil SYSCALL_REQUIRE((child = fork()) != -1); 4161.59Skamil if (child == 0) { 4171.59Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 4181.59Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 4191.59Skamil 4201.59Skamil DPRINTF("Before executing a trap\n"); 4211.59Skamil switch (sig) { 4221.59Skamil case SIGTRAP: 4231.59Skamil trigger_trap(); 4241.59Skamil break; 4251.59Skamil case SIGSEGV: 4261.59Skamil trigger_segv(); 4271.59Skamil break; 4281.59Skamil case SIGILL: 4291.59Skamil trigger_ill(); 4301.59Skamil break; 4311.59Skamil case SIGFPE: 4321.59Skamil trigger_fpe(); 4331.59Skamil break; 4341.59Skamil case SIGBUS: 4351.59Skamil trigger_bus(); 4361.59Skamil break; 4371.59Skamil default: 4381.59Skamil /* NOTREACHED */ 4391.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4401.59Skamil } 4411.59Skamil 4421.59Skamil /* NOTREACHED */ 4431.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4441.59Skamil } 4451.59Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 4461.59Skamil 4471.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4481.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4491.59Skamil 4501.59Skamil validate_status_stopped(status, sig); 4511.59Skamil 4521.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 4531.61Skre SYSCALL_REQUIRE( 4541.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 4551.59Skamil 4561.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 4571.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 4581.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 4591.61Skre info.psi_siginfo.si_errno); 4601.59Skamil 4611.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 4621.59Skamil switch (sig) { 4631.59Skamil case SIGTRAP: 4641.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 4651.59Skamil break; 4661.59Skamil case SIGSEGV: 4671.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 4681.59Skamil break; 4691.71Skamil case SIGILL: 4701.71Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC); 4711.71Skamil break; 4721.59Skamil case SIGFPE: 4731.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 4741.59Skamil break; 4751.59Skamil case SIGBUS: 4761.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 4771.59Skamil break; 4781.59Skamil } 4791.59Skamil 4801.59Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 4811.59Skamil 4821.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4831.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4841.59Skamil 4851.59Skamil validate_status_signaled(status, SIGKILL, 0); 4861.59Skamil 4871.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4881.59Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 4891.59Skamil} 4901.59Skamil 4911.61Skre#define TRACEME_CRASH(test, sig) \ 4921.61SkreATF_TC(test); \ 4931.61SkreATF_TC_HEAD(test, tc) \ 4941.61Skre{ \ 4951.61Skre atf_tc_set_md_var(tc, "descr", \ 4961.61Skre "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \ 4971.61Skre} \ 4981.61Skre \ 4991.61SkreATF_TC_BODY(test, tc) \ 5001.61Skre{ \ 5011.61Skre \ 5021.61Skre traceme_crash(sig); \ 5031.59Skamil} 5041.59Skamil 5051.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP) 5061.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV) 5071.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL) 5081.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE) 5091.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS) 5101.59Skamil 5111.59Skamil/// ---------------------------------------------------------------------------- 5121.59Skamil 5131.59Skamilstatic void 5141.88Skamiltraceme_signalmasked_crash(int sig) 5151.88Skamil{ 5161.89Skamil const int sigval = SIGSTOP; 5171.88Skamil pid_t child, wpid; 5181.88Skamil#if defined(TWAIT_HAVE_STATUS) 5191.88Skamil int status; 5201.88Skamil#endif 5211.88Skamil struct ptrace_siginfo info; 5221.88Skamil sigset_t intmask; 5231.89Skamil struct kinfo_proc2 kp; 5241.89Skamil size_t len = sizeof(kp); 5251.89Skamil 5261.89Skamil int name[6]; 5271.89Skamil const size_t namelen = __arraycount(name); 5281.89Skamil ki_sigset_t kp_sigmask; 5291.88Skamil 5301.88Skamil#ifndef PTRACE_ILLEGAL_ASM 5311.88Skamil if (sig == SIGILL) 5321.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 5331.88Skamil#endif 5341.88Skamil 5351.88Skamil memset(&info, 0, sizeof(info)); 5361.88Skamil 5371.89Skamil atf_tc_expect_fail("Unexpected sigmask reset on crash under debugger"); 5381.89Skamil 5391.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 5401.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 5411.88Skamil if (child == 0) { 5421.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 5431.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 5441.88Skamil 5451.88Skamil sigemptyset(&intmask); 5461.88Skamil sigaddset(&intmask, sig); 5471.88Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 5481.88Skamil 5491.89Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 5501.89Skamil FORKEE_ASSERT(raise(sigval) == 0); 5511.89Skamil 5521.88Skamil DPRINTF("Before executing a trap\n"); 5531.88Skamil switch (sig) { 5541.88Skamil case SIGTRAP: 5551.88Skamil trigger_trap(); 5561.88Skamil break; 5571.88Skamil case SIGSEGV: 5581.88Skamil trigger_segv(); 5591.88Skamil break; 5601.88Skamil case SIGILL: 5611.88Skamil trigger_ill(); 5621.88Skamil break; 5631.88Skamil case SIGFPE: 5641.88Skamil trigger_fpe(); 5651.88Skamil break; 5661.88Skamil case SIGBUS: 5671.88Skamil trigger_bus(); 5681.88Skamil break; 5691.88Skamil default: 5701.88Skamil /* NOTREACHED */ 5711.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 5721.88Skamil } 5731.88Skamil 5741.88Skamil /* NOTREACHED */ 5751.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 5761.88Skamil } 5771.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 5781.88Skamil 5791.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5801.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 5811.88Skamil 5821.89Skamil validate_status_stopped(status, sigval); 5831.89Skamil 5841.89Skamil name[0] = CTL_KERN, 5851.89Skamil name[1] = KERN_PROC2, 5861.89Skamil name[2] = KERN_PROC_PID; 5871.89Skamil name[3] = child; 5881.89Skamil name[4] = sizeof(kp); 5891.89Skamil name[5] = 1; 5901.89Skamil 5911.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 5921.89Skamil 5931.89Skamil kp_sigmask = kp.p_sigmask; 5941.89Skamil 5951.89Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 5961.89Skamil SYSCALL_REQUIRE( 5971.89Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 5981.89Skamil 5991.89Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6001.89Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6011.89Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6021.89Skamil info.psi_siginfo.si_errno); 6031.89Skamil 6041.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 6051.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 6061.89Skamil 6071.89Skamil DPRINTF("Before resuming the child process where it left off and " 6081.89Skamil "without signal to be sent\n"); 6091.89Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 6101.89Skamil 6111.89Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6121.89Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6131.89Skamil 6141.88Skamil validate_status_stopped(status, sig); 6151.88Skamil 6161.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 6171.88Skamil SYSCALL_REQUIRE( 6181.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6191.88Skamil 6201.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6211.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6221.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6231.88Skamil info.psi_siginfo.si_errno); 6241.88Skamil 6251.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6261.89Skamil 6271.89Skamil DPRINTF("kp_sigmask=" 6281.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6291.89Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2], 6301.89Skamil kp_sigmask.__bits[3]); 6311.89Skamil 6321.89Skamil DPRINTF("kp.p_sigmask=" 6331.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6341.89Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 6351.89Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 6361.89Skamil 6371.89Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask))); 6381.89Skamil 6391.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 6401.88Skamil switch (sig) { 6411.88Skamil case SIGTRAP: 6421.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 6431.88Skamil break; 6441.88Skamil case SIGSEGV: 6451.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 6461.88Skamil break; 6471.88Skamil case SIGILL: 6481.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC); 6491.88Skamil break; 6501.88Skamil case SIGFPE: 6511.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 6521.88Skamil break; 6531.88Skamil case SIGBUS: 6541.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 6551.88Skamil break; 6561.88Skamil } 6571.88Skamil 6581.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 6591.88Skamil 6601.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6611.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6621.88Skamil 6631.88Skamil validate_status_signaled(status, SIGKILL, 0); 6641.88Skamil 6651.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6661.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 6671.88Skamil} 6681.88Skamil 6691.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig) \ 6701.88SkamilATF_TC(test); \ 6711.88SkamilATF_TC_HEAD(test, tc) \ 6721.88Skamil{ \ 6731.88Skamil atf_tc_set_md_var(tc, "descr", \ 6741.88Skamil "Verify masked crash signal " #sig " in a child after " \ 6751.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 6761.88Skamil} \ 6771.88Skamil \ 6781.88SkamilATF_TC_BODY(test, tc) \ 6791.88Skamil{ \ 6801.88Skamil \ 6811.88Skamil traceme_signalmasked_crash(sig); \ 6821.88Skamil} 6831.88Skamil 6841.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP) 6851.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV) 6861.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL) 6871.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE) 6881.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS) 6891.88Skamil 6901.88Skamil/// ---------------------------------------------------------------------------- 6911.88Skamil 6921.88Skamilstatic void 6931.88Skamiltraceme_signalignored_crash(int sig) 6941.88Skamil{ 6951.90Skamil const int sigval = SIGSTOP; 6961.88Skamil pid_t child, wpid; 6971.88Skamil#if defined(TWAIT_HAVE_STATUS) 6981.88Skamil int status; 6991.88Skamil#endif 7001.88Skamil struct sigaction sa; 7011.88Skamil struct ptrace_siginfo info; 7021.90Skamil struct kinfo_proc2 kp; 7031.90Skamil size_t len = sizeof(kp); 7041.90Skamil 7051.90Skamil int name[6]; 7061.90Skamil const size_t namelen = __arraycount(name); 7071.90Skamil ki_sigset_t kp_sigignore; 7081.88Skamil 7091.88Skamil#ifndef PTRACE_ILLEGAL_ASM 7101.88Skamil if (sig == SIGILL) 7111.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 7121.88Skamil#endif 7131.88Skamil 7141.90Skamil atf_tc_expect_fail("Unexpected sigmask reset on crash under debugger"); 7151.90Skamil 7161.88Skamil memset(&info, 0, sizeof(info)); 7171.88Skamil 7181.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 7191.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 7201.88Skamil if (child == 0) { 7211.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 7221.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 7231.88Skamil 7241.88Skamil memset(&sa, 0, sizeof(sa)); 7251.88Skamil sa.sa_handler = SIG_IGN; 7261.88Skamil sigemptyset(&sa.sa_mask); 7271.88Skamil 7281.88Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 7291.88Skamil 7301.90Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 7311.90Skamil FORKEE_ASSERT(raise(sigval) == 0); 7321.90Skamil 7331.88Skamil DPRINTF("Before executing a trap\n"); 7341.88Skamil switch (sig) { 7351.88Skamil case SIGTRAP: 7361.88Skamil trigger_trap(); 7371.88Skamil break; 7381.88Skamil case SIGSEGV: 7391.88Skamil trigger_segv(); 7401.88Skamil break; 7411.88Skamil case SIGILL: 7421.88Skamil trigger_ill(); 7431.88Skamil break; 7441.88Skamil case SIGFPE: 7451.88Skamil trigger_fpe(); 7461.88Skamil break; 7471.88Skamil case SIGBUS: 7481.88Skamil trigger_bus(); 7491.88Skamil break; 7501.88Skamil default: 7511.88Skamil /* NOTREACHED */ 7521.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7531.88Skamil } 7541.88Skamil 7551.88Skamil /* NOTREACHED */ 7561.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7571.88Skamil } 7581.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 7591.88Skamil 7601.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7611.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 7621.88Skamil 7631.90Skamil validate_status_stopped(status, sigval); 7641.90Skamil 7651.90Skamil name[0] = CTL_KERN, 7661.90Skamil name[1] = KERN_PROC2, 7671.90Skamil name[2] = KERN_PROC_PID; 7681.90Skamil name[3] = child; 7691.90Skamil name[4] = sizeof(kp); 7701.90Skamil name[5] = 1; 7711.90Skamil 7721.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 7731.90Skamil 7741.90Skamil kp_sigignore = kp.p_sigignore; 7751.90Skamil 7761.90Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 7771.90Skamil SYSCALL_REQUIRE( 7781.90Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 7791.90Skamil 7801.90Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 7811.90Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 7821.90Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 7831.90Skamil info.psi_siginfo.si_errno); 7841.90Skamil 7851.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 7861.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 7871.90Skamil 7881.90Skamil DPRINTF("Before resuming the child process where it left off and " 7891.90Skamil "without signal to be sent\n"); 7901.90Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 7911.90Skamil 7921.90Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7931.90Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 7941.90Skamil 7951.88Skamil validate_status_stopped(status, sig); 7961.88Skamil 7971.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 7981.88Skamil SYSCALL_REQUIRE( 7991.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8001.88Skamil 8011.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8021.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8031.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8041.88Skamil info.psi_siginfo.si_errno); 8051.88Skamil 8061.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8071.90Skamil 8081.90Skamil DPRINTF("kp_sigignore=" 8091.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8101.90Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 8111.90Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 8121.90Skamil 8131.90Skamil DPRINTF("kp.p_sigignore=" 8141.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8151.90Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 8161.90Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 8171.90Skamil 8181.90Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore))); 8191.90Skamil 8201.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 8211.88Skamil switch (sig) { 8221.88Skamil case SIGTRAP: 8231.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 8241.88Skamil break; 8251.88Skamil case SIGSEGV: 8261.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 8271.88Skamil break; 8281.88Skamil case SIGILL: 8291.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, ILL_PRVOPC); 8301.88Skamil break; 8311.88Skamil case SIGFPE: 8321.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 8331.88Skamil break; 8341.88Skamil case SIGBUS: 8351.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 8361.88Skamil break; 8371.88Skamil } 8381.88Skamil 8391.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 8401.88Skamil 8411.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8421.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8431.88Skamil 8441.88Skamil validate_status_signaled(status, SIGKILL, 0); 8451.88Skamil 8461.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8471.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 8481.88Skamil} 8491.88Skamil 8501.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig) \ 8511.88SkamilATF_TC(test); \ 8521.88SkamilATF_TC_HEAD(test, tc) \ 8531.88Skamil{ \ 8541.88Skamil atf_tc_set_md_var(tc, "descr", \ 8551.88Skamil "Verify ignored crash signal " #sig " in a child after " \ 8561.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 8571.88Skamil} \ 8581.88Skamil \ 8591.88SkamilATF_TC_BODY(test, tc) \ 8601.88Skamil{ \ 8611.88Skamil \ 8621.88Skamil traceme_signalignored_crash(sig); \ 8631.88Skamil} 8641.88Skamil 8651.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP) 8661.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV) 8671.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL) 8681.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE) 8691.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS) 8701.88Skamil 8711.88Skamil/// ---------------------------------------------------------------------------- 8721.88Skamil 8731.88Skamilstatic void 8741.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught) 8751.1Skamil{ 8761.1Skamil const int exitval = 5; 8771.34Skamil const int sigval = SIGSTOP; 8781.1Skamil pid_t child, wpid; 8791.1Skamil struct sigaction sa; 8801.1Skamil#if defined(TWAIT_HAVE_STATUS) 8811.1Skamil int status; 8821.1Skamil#endif 8831.61Skre struct ptrace_siginfo info; 8841.1Skamil 8851.45Skamil memset(&info, 0, sizeof(info)); 8861.45Skamil 8871.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 8881.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 8891.1Skamil if (child == 0) { 8901.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 8911.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 8921.1Skamil 8931.34Skamil sa.sa_handler = sah; 8941.1Skamil sa.sa_flags = SA_SIGINFO; 8951.1Skamil sigemptyset(&sa.sa_mask); 8961.1Skamil 8971.1Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 8981.1Skamil 8991.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 9001.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 9011.1Skamil 9021.34Skamil FORKEE_ASSERT_EQ(*traceme_caught, 1); 9031.1Skamil 9041.13Schristos DPRINTF("Before exiting of the child process\n"); 9051.1Skamil _exit(exitval); 9061.1Skamil } 9071.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 9081.1Skamil 9091.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9101.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9111.1Skamil 9121.1Skamil validate_status_stopped(status, sigval); 9131.1Skamil 9141.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 9151.61Skre SYSCALL_REQUIRE( 9161.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 9171.45Skamil 9181.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 9191.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 9201.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 9211.45Skamil info.psi_siginfo.si_errno); 9221.45Skamil 9231.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 9241.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 9251.45Skamil 9261.13Schristos DPRINTF("Before resuming the child process where it left off and with " 9271.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 9281.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 9291.1Skamil 9301.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9311.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9321.1Skamil 9331.1Skamil validate_status_exited(status, exitval); 9341.1Skamil 9351.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 9361.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 9371.1Skamil} 9381.1Skamil 9391.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig) \ 9401.61SkreATF_TC(test); \ 9411.61SkreATF_TC_HEAD(test, tc) \ 9421.61Skre{ \ 9431.61Skre atf_tc_set_md_var(tc, "descr", \ 9441.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 9451.61Skre "handled correctly and caught by a signal handler"); \ 9461.61Skre} \ 9471.61Skre \ 9481.61Skrestatic int test##_caught = 0; \ 9491.61Skre \ 9501.61Skrestatic void \ 9511.61Skretest##_sighandler(int arg) \ 9521.61Skre{ \ 9531.61Skre FORKEE_ASSERT_EQ(arg, sig); \ 9541.61Skre \ 9551.61Skre ++ test##_caught; \ 9561.61Skre} \ 9571.61Skre \ 9581.61SkreATF_TC_BODY(test, tc) \ 9591.61Skre{ \ 9601.61Skre \ 9611.61Skre traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \ 9621.34Skamil} 9631.34Skamil 9641.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered. 9651.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */ 9661.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP) /* hangup */ 9671.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */ 9681.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */ 9691.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */ 9701.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */ 9711.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */ 9721.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */ 9731.34Skamil 9741.34Skamil/// ---------------------------------------------------------------------------- 9751.34Skamil 9761.35Skamilstatic void 9771.50Skamiltraceme_sendsignal_masked(int sigsent) 9781.50Skamil{ 9791.50Skamil const int exitval = 5; 9801.50Skamil const int sigval = SIGSTOP; 9811.50Skamil pid_t child, wpid; 9821.50Skamil sigset_t set; 9831.50Skamil#if defined(TWAIT_HAVE_STATUS) 9841.50Skamil int status; 9851.50Skamil#endif 9861.61Skre struct ptrace_siginfo info; 9871.50Skamil 9881.50Skamil memset(&info, 0, sizeof(info)); 9891.50Skamil 9901.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 9911.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 9921.50Skamil if (child == 0) { 9931.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 9941.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 9951.50Skamil 9961.50Skamil sigemptyset(&set); 9971.50Skamil sigaddset(&set, sigsent); 9981.50Skamil FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 9991.50Skamil 10001.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 10011.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 10021.50Skamil 10031.50Skamil _exit(exitval); 10041.50Skamil } 10051.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 10061.50Skamil 10071.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10081.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10091.50Skamil 10101.50Skamil validate_status_stopped(status, sigval); 10111.50Skamil 10121.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 10131.61Skre SYSCALL_REQUIRE( 10141.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 10151.50Skamil 10161.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 10171.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 10181.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 10191.50Skamil info.psi_siginfo.si_errno); 10201.50Skamil 10211.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 10221.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 10231.50Skamil 10241.50Skamil DPRINTF("Before resuming the child process where it left off and with " 10251.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 10261.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 10271.50Skamil 10281.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10291.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10301.50Skamil 10311.50Skamil validate_status_exited(status, exitval); 10321.50Skamil 10331.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 10341.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 10351.50Skamil} 10361.50Skamil 10371.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig) \ 10381.61SkreATF_TC(test); \ 10391.61SkreATF_TC_HEAD(test, tc) \ 10401.61Skre{ \ 10411.61Skre atf_tc_set_md_var(tc, "descr", \ 10421.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 10431.61Skre "handled correctly and the signal is masked by SIG_BLOCK"); \ 10441.61Skre} \ 10451.61Skre \ 10461.61SkreATF_TC_BODY(test, tc) \ 10471.61Skre{ \ 10481.61Skre \ 10491.61Skre traceme_sendsignal_masked(sig); \ 10501.50Skamil} 10511.50Skamil 10521.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 10531.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */ 10541.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP) /* hangup */ 10551.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */ 10561.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */ 10571.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */ 10581.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */ 10591.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */ 10601.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */ 10611.50Skamil 10621.50Skamil/// ---------------------------------------------------------------------------- 10631.50Skamil 10641.50Skamilstatic void 10651.50Skamiltraceme_sendsignal_ignored(int sigsent) 10661.50Skamil{ 10671.50Skamil const int exitval = 5; 10681.50Skamil const int sigval = SIGSTOP; 10691.50Skamil pid_t child, wpid; 10701.50Skamil struct sigaction sa; 10711.50Skamil#if defined(TWAIT_HAVE_STATUS) 10721.50Skamil int status; 10731.50Skamil#endif 10741.61Skre struct ptrace_siginfo info; 10751.50Skamil 10761.50Skamil memset(&info, 0, sizeof(info)); 10771.50Skamil 10781.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 10791.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 10801.50Skamil if (child == 0) { 10811.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 10821.61Skre 10831.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 10841.50Skamil 10851.50Skamil memset(&sa, 0, sizeof(sa)); 10861.50Skamil sa.sa_handler = SIG_IGN; 10871.50Skamil sigemptyset(&sa.sa_mask); 10881.50Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 10891.50Skamil 10901.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 10911.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 10921.50Skamil 10931.50Skamil _exit(exitval); 10941.50Skamil } 10951.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 10961.50Skamil 10971.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10981.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10991.50Skamil 11001.50Skamil validate_status_stopped(status, sigval); 11011.50Skamil 11021.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 11031.61Skre SYSCALL_REQUIRE( 11041.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 11051.50Skamil 11061.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 11071.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 11081.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 11091.50Skamil info.psi_siginfo.si_errno); 11101.50Skamil 11111.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 11121.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 11131.50Skamil 11141.50Skamil DPRINTF("Before resuming the child process where it left off and with " 11151.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 11161.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 11171.50Skamil 11181.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11191.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11201.50Skamil 11211.50Skamil validate_status_exited(status, exitval); 11221.50Skamil 11231.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 11241.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 11251.50Skamil} 11261.50Skamil 11271.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig) \ 11281.61SkreATF_TC(test); \ 11291.61SkreATF_TC_HEAD(test, tc) \ 11301.61Skre{ \ 11311.61Skre atf_tc_set_md_var(tc, "descr", \ 11321.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 11331.61Skre "handled correctly and the signal is masked by SIG_IGN"); \ 11341.61Skre} \ 11351.61Skre \ 11361.61SkreATF_TC_BODY(test, tc) \ 11371.61Skre{ \ 11381.61Skre \ 11391.61Skre traceme_sendsignal_ignored(sig); \ 11401.50Skamil} 11411.50Skamil 11421.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 11431.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */ 11441.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP) /* hangup */ 11451.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */ 11461.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */ 11471.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */ 11481.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */ 11491.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */ 11501.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */ 11511.50Skamil 11521.50Skamil/// ---------------------------------------------------------------------------- 11531.50Skamil 11541.50Skamilstatic void 11551.50Skamiltraceme_sendsignal_simple(int sigsent) 11561.1Skamil{ 11571.35Skamil const int sigval = SIGSTOP; 11581.35Skamil int exitval = 0; 11591.1Skamil pid_t child, wpid; 11601.1Skamil#if defined(TWAIT_HAVE_STATUS) 11611.1Skamil int status; 11621.85Skamil int expect_core; 11631.85Skamil 11641.85Skamil switch (sigsent) { 11651.85Skamil case SIGABRT: 11661.85Skamil case SIGTRAP: 11671.85Skamil case SIGBUS: 11681.85Skamil case SIGILL: 11691.85Skamil case SIGFPE: 11701.85Skamil case SIGSEGV: 11711.85Skamil expect_core = 1; 11721.85Skamil break; 11731.85Skamil default: 11741.85Skamil expect_core = 0; 11751.85Skamil break; 11761.85Skamil } 11771.1Skamil#endif 11781.61Skre struct ptrace_siginfo info; 11791.1Skamil 11801.45Skamil memset(&info, 0, sizeof(info)); 11811.45Skamil 11821.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 11831.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 11841.1Skamil if (child == 0) { 11851.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 11861.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 11871.1Skamil 11881.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 11891.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 11901.1Skamil 11911.35Skamil switch (sigsent) { 11921.35Skamil case SIGCONT: 11931.48Skamil case SIGSTOP: 11941.35Skamil _exit(exitval); 11951.35Skamil default: 11961.35Skamil /* NOTREACHED */ 11971.35Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 11981.35Skamil } 11991.1Skamil } 12001.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 12011.1Skamil 12021.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12031.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12041.1Skamil 12051.1Skamil validate_status_stopped(status, sigval); 12061.1Skamil 12071.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 12081.61Skre SYSCALL_REQUIRE( 12091.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 12101.45Skamil 12111.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12121.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 12131.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12141.45Skamil info.psi_siginfo.si_errno); 12151.45Skamil 12161.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12171.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12181.45Skamil 12191.13Schristos DPRINTF("Before resuming the child process where it left off and with " 12201.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 12211.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 12221.1Skamil 12231.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12241.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12251.1Skamil 12261.35Skamil switch (sigsent) { 12271.48Skamil case SIGSTOP: 12281.48Skamil validate_status_stopped(status, sigsent); 12291.48Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 12301.61Skre "child\n"); 12311.48Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 12321.61Skre sizeof(info)) != -1); 12331.48Skamil 12341.48Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12351.48Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 12361.61Skre "si_errno=%#x\n", 12371.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12381.61Skre info.psi_siginfo.si_errno); 12391.48Skamil 12401.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12411.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12421.48Skamil 12431.48Skamil DPRINTF("Before resuming the child process where it left off " 12441.61Skre "and with signal %s to be sent\n", strsignal(sigsent)); 12451.48Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 12461.48Skamil 12471.48Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12481.48Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 12491.61Skre child); 12501.48Skamil /* FALLTHROUGH */ 12511.35Skamil case SIGCONT: 12521.35Skamil validate_status_exited(status, exitval); 12531.35Skamil break; 12541.35Skamil default: 12551.35Skamil validate_status_signaled(status, sigsent, expect_core); 12561.35Skamil break; 12571.35Skamil } 12581.1Skamil 12591.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 12601.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 12611.1Skamil} 12621.1Skamil 12631.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig) \ 12641.61SkreATF_TC(test); \ 12651.61SkreATF_TC_HEAD(test, tc) \ 12661.61Skre{ \ 12671.61Skre atf_tc_set_md_var(tc, "descr", \ 12681.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 12691.61Skre "handled correctly in a child without a signal handler"); \ 12701.61Skre} \ 12711.61Skre \ 12721.61SkreATF_TC_BODY(test, tc) \ 12731.61Skre{ \ 12741.61Skre \ 12751.61Skre traceme_sendsignal_simple(sig); \ 12761.35Skamil} 12771.35Skamil 12781.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/ 12791.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/ 12801.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */ 12811.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP) /* hangup */ 12821.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */ 12831.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */ 12841.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */ 12851.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */ 12861.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */ 12871.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */ 12881.35Skamil 12891.35Skamil/// ---------------------------------------------------------------------------- 12901.35Skamil 12911.37SkamilATF_TC(traceme_pid1_parent); 12921.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc) 12931.37Skamil{ 12941.37Skamil atf_tc_set_md_var(tc, "descr", 12951.37Skamil "Verify that PT_TRACE_ME is not allowed when our parent is PID1"); 12961.37Skamil} 12971.37Skamil 12981.37SkamilATF_TC_BODY(traceme_pid1_parent, tc) 12991.37Skamil{ 13001.37Skamil struct msg_fds parent_child; 13011.37Skamil int exitval_child1 = 1, exitval_child2 = 2; 13021.37Skamil pid_t child1, child2, wpid; 13031.37Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 13041.37Skamil#if defined(TWAIT_HAVE_STATUS) 13051.37Skamil int status; 13061.37Skamil#endif 13071.37Skamil 13081.37Skamil SYSCALL_REQUIRE(msg_open(&parent_child) == 0); 13091.37Skamil 13101.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13111.37Skamil SYSCALL_REQUIRE((child1 = fork()) != -1); 13121.37Skamil if (child1 == 0) { 13131.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13141.37Skamil SYSCALL_REQUIRE((child2 = fork()) != -1); 13151.37Skamil if (child2 != 0) { 13161.37Skamil DPRINTF("Parent process PID=%d, child2's PID=%d\n", 13171.61Skre getpid(), child2); 13181.37Skamil _exit(exitval_child1); 13191.37Skamil } 13201.37Skamil CHILD_FROM_PARENT("exit child1", parent_child, msg); 13211.37Skamil 13221.37Skamil DPRINTF("Assert that our parent is PID1 (initproc)\n"); 13231.37Skamil FORKEE_ASSERT_EQ(getppid(), 1); 13241.37Skamil 13251.37Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 13261.37Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1); 13271.37Skamil SYSCALL_REQUIRE_ERRNO(errno, EPERM); 13281.37Skamil 13291.37Skamil CHILD_TO_PARENT("child2 exiting", parent_child, msg); 13301.37Skamil 13311.37Skamil _exit(exitval_child2); 13321.37Skamil } 13331.37Skamil DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1); 13341.37Skamil 13351.37Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 13361.61Skre TWAIT_REQUIRE_SUCCESS( 13371.61Skre wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1); 13381.37Skamil 13391.37Skamil validate_status_exited(status, exitval_child1); 13401.37Skamil 13411.37Skamil DPRINTF("Notify that child1 is dead\n"); 13421.37Skamil PARENT_TO_CHILD("exit child1", parent_child, msg); 13431.37Skamil 13441.37Skamil DPRINTF("Wait for exiting of child2\n"); 13451.37Skamil PARENT_FROM_CHILD("child2 exiting", parent_child, msg); 13461.37Skamil} 13471.37Skamil 13481.37Skamil/// ---------------------------------------------------------------------------- 13491.37Skamil 13501.40Skamilstatic void 13511.40Skamiltraceme_vfork_raise(int sigval) 13521.40Skamil{ 13531.46Skamil const int exitval = 5, exitval_watcher = 10; 13541.46Skamil pid_t child, parent, watcher, wpid; 13551.46Skamil int rv; 13561.40Skamil#if defined(TWAIT_HAVE_STATUS) 13571.40Skamil int status; 13581.85Skamil 13591.85Skamil /* volatile workarounds GCC -Werror=clobbered */ 13601.85Skamil volatile int expect_core; 13611.85Skamil 13621.85Skamil switch (sigval) { 13631.85Skamil case SIGABRT: 13641.85Skamil case SIGTRAP: 13651.85Skamil case SIGBUS: 13661.85Skamil case SIGILL: 13671.85Skamil case SIGFPE: 13681.85Skamil case SIGSEGV: 13691.85Skamil expect_core = 1; 13701.85Skamil break; 13711.85Skamil default: 13721.85Skamil expect_core = 0; 13731.85Skamil break; 13741.85Skamil } 13751.40Skamil#endif 13761.40Skamil 13771.46Skamil /* 13781.46Skamil * Spawn a dedicated thread to watch for a stopped child and emit 13791.46Skamil * the SIGKILL signal to it. 13801.46Skamil * 13811.46Skamil * vfork(2) might clobber watcher, this means that it's safer and 13821.46Skamil * simpler to reparent this process to initproc and forget about it. 13831.46Skamil */ 13841.46Skamil if (sigval == SIGSTOP) { 13851.46Skamil parent = getpid(); 13861.46Skamil 13871.46Skamil watcher = fork(); 13881.46Skamil ATF_REQUIRE(watcher != 1); 13891.46Skamil if (watcher == 0) { 13901.46Skamil /* Double fork(2) trick to reparent to initproc */ 13911.46Skamil watcher = fork(); 13921.46Skamil FORKEE_ASSERT_NEQ(watcher, -1); 13931.46Skamil if (watcher != 0) 13941.46Skamil _exit(exitval_watcher); 13951.46Skamil 13961.46Skamil child = await_stopped_child(parent); 13971.46Skamil 13981.46Skamil errno = 0; 13991.46Skamil rv = kill(child, SIGKILL); 14001.46Skamil FORKEE_ASSERT_EQ(rv, 0); 14011.46Skamil FORKEE_ASSERT_EQ(errno, 0); 14021.46Skamil 14031.46Skamil /* This exit value will be collected by initproc */ 14041.46Skamil _exit(0); 14051.46Skamil } 14061.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14071.46Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0), 14081.61Skre watcher); 14091.46Skamil 14101.46Skamil validate_status_exited(status, exitval_watcher); 14111.46Skamil 14121.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14131.61Skre TWAIT_REQUIRE_FAILURE(ECHILD, 14141.61Skre wpid = TWAIT_GENERIC(watcher, &status, 0)); 14151.46Skamil } 14161.46Skamil 14171.40Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 14181.40Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 14191.40Skamil if (child == 0) { 14201.40Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 14211.40Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 14221.40Skamil 14231.40Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 14241.40Skamil FORKEE_ASSERT(raise(sigval) == 0); 14251.40Skamil 14261.40Skamil switch (sigval) { 14271.46Skamil case SIGSTOP: 14281.40Skamil case SIGKILL: 14291.40Skamil case SIGABRT: 14301.40Skamil case SIGHUP: 14311.85Skamil case SIGTRAP: 14321.85Skamil case SIGBUS: 14331.85Skamil case SIGILL: 14341.85Skamil case SIGFPE: 14351.85Skamil case SIGSEGV: 14361.40Skamil /* NOTREACHED */ 14371.40Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 14381.70Smrg __unreachable(); 14391.40Skamil default: 14401.40Skamil DPRINTF("Before exiting of the child process\n"); 14411.40Skamil _exit(exitval); 14421.40Skamil } 14431.40Skamil } 14441.40Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 14451.40Skamil 14461.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14471.40Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 14481.40Skamil 14491.40Skamil switch (sigval) { 14501.40Skamil case SIGKILL: 14511.40Skamil case SIGABRT: 14521.40Skamil case SIGHUP: 14531.85Skamil case SIGTRAP: 14541.85Skamil case SIGBUS: 14551.85Skamil case SIGILL: 14561.85Skamil case SIGFPE: 14571.85Skamil case SIGSEGV: 14581.40Skamil validate_status_signaled(status, sigval, expect_core); 14591.40Skamil break; 14601.40Skamil case SIGSTOP: 14611.46Skamil validate_status_signaled(status, SIGKILL, 0); 14621.46Skamil break; 14631.40Skamil case SIGCONT: 14641.47Skamil case SIGTSTP: 14651.47Skamil case SIGTTIN: 14661.47Skamil case SIGTTOU: 14671.40Skamil validate_status_exited(status, exitval); 14681.40Skamil break; 14691.40Skamil default: 14701.40Skamil /* NOTREACHED */ 14711.40Skamil ATF_REQUIRE(0 && "NOT IMPLEMENTED"); 14721.40Skamil break; 14731.40Skamil } 14741.40Skamil 14751.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14761.40Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 14771.40Skamil} 14781.40Skamil 14791.61Skre#define TRACEME_VFORK_RAISE(test, sig) \ 14801.61SkreATF_TC(test); \ 14811.61SkreATF_TC_HEAD(test, tc) \ 14821.61Skre{ \ 14831.61Skre atf_tc_set_md_var(tc, "descr", \ 14841.61Skre "Verify PT_TRACE_ME followed by raise of " #sig " in a " \ 14851.61Skre "vfork(2)ed child"); \ 14861.61Skre} \ 14871.61Skre \ 14881.61SkreATF_TC_BODY(test, tc) \ 14891.61Skre{ \ 14901.61Skre \ 14911.61Skre traceme_vfork_raise(sig); \ 14921.40Skamil} 14931.40Skamil 14941.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */ 14951.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */ 14961.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */ 14971.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */ 14981.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */ 14991.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */ 15001.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP) /* hangup */ 15011.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */ 15021.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */ 15031.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */ 15041.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */ 15051.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */ 15061.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */ 15071.40Skamil 15081.40Skamil/// ---------------------------------------------------------------------------- 15091.40Skamil 15101.52Skamilstatic void 15111.52Skamiltraceme_vfork_crash(int sig) 15121.41Skamil{ 15131.41Skamil pid_t child, wpid; 15141.41Skamil#if defined(TWAIT_HAVE_STATUS) 15151.41Skamil int status; 15161.41Skamil#endif 15171.41Skamil 15181.71Skamil#ifndef PTRACE_ILLEGAL_ASM 15191.71Skamil if (sig == SIGILL) 15201.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 15211.71Skamil#endif 15221.71Skamil 15231.41Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 15241.41Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 15251.41Skamil if (child == 0) { 15261.41Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 15271.41Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 15281.41Skamil 15291.52Skamil DPRINTF("Before executing a trap\n"); 15301.52Skamil switch (sig) { 15311.52Skamil case SIGTRAP: 15321.52Skamil trigger_trap(); 15331.52Skamil break; 15341.52Skamil case SIGSEGV: 15351.52Skamil trigger_segv(); 15361.52Skamil break; 15371.52Skamil case SIGILL: 15381.52Skamil trigger_ill(); 15391.52Skamil break; 15401.52Skamil case SIGFPE: 15411.52Skamil trigger_fpe(); 15421.52Skamil break; 15431.52Skamil case SIGBUS: 15441.52Skamil trigger_bus(); 15451.52Skamil break; 15461.52Skamil default: 15471.52Skamil /* NOTREACHED */ 15481.52Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15491.52Skamil } 15501.41Skamil 15511.41Skamil /* NOTREACHED */ 15521.41Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15531.41Skamil } 15541.41Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 15551.41Skamil 15561.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15571.41Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 15581.41Skamil 15591.52Skamil validate_status_signaled(status, sig, 1); 15601.41Skamil 15611.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15621.41Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15631.41Skamil} 15641.41Skamil 15651.61Skre#define TRACEME_VFORK_CRASH(test, sig) \ 15661.61SkreATF_TC(test); \ 15671.61SkreATF_TC_HEAD(test, tc) \ 15681.61Skre{ \ 15691.61Skre atf_tc_set_md_var(tc, "descr", \ 15701.61Skre "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 15711.61Skre "vfork(2)ed child"); \ 15721.61Skre} \ 15731.61Skre \ 15741.61SkreATF_TC_BODY(test, tc) \ 15751.61Skre{ \ 15761.61Skre \ 15771.61Skre traceme_vfork_crash(sig); \ 15781.52Skamil} 15791.52Skamil 15801.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP) 15811.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV) 15821.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL) 15831.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE) 15841.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS) 15851.52Skamil 15861.41Skamil/// ---------------------------------------------------------------------------- 15871.41Skamil 15881.92Skamilstatic void 15891.92Skamiltraceme_vfork_signalmasked_crash(int sig) 15901.92Skamil{ 15911.92Skamil pid_t child, wpid; 15921.92Skamil#if defined(TWAIT_HAVE_STATUS) 15931.92Skamil int status; 15941.92Skamil#endif 15951.92Skamil sigset_t intmask; 15961.92Skamil 15971.92Skamil#ifndef PTRACE_ILLEGAL_ASM 15981.92Skamil if (sig == SIGILL) 15991.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 16001.92Skamil#endif 16011.92Skamil 16021.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 16031.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 16041.92Skamil if (child == 0) { 16051.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 16061.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 16071.92Skamil 16081.92Skamil sigemptyset(&intmask); 16091.92Skamil sigaddset(&intmask, sig); 16101.92Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 16111.92Skamil 16121.92Skamil DPRINTF("Before executing a trap\n"); 16131.92Skamil switch (sig) { 16141.92Skamil case SIGTRAP: 16151.92Skamil trigger_trap(); 16161.92Skamil break; 16171.92Skamil case SIGSEGV: 16181.92Skamil trigger_segv(); 16191.92Skamil break; 16201.92Skamil case SIGILL: 16211.92Skamil trigger_ill(); 16221.92Skamil break; 16231.92Skamil case SIGFPE: 16241.92Skamil trigger_fpe(); 16251.92Skamil break; 16261.92Skamil case SIGBUS: 16271.92Skamil trigger_bus(); 16281.92Skamil break; 16291.92Skamil default: 16301.92Skamil /* NOTREACHED */ 16311.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16321.92Skamil } 16331.92Skamil 16341.92Skamil /* NOTREACHED */ 16351.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16361.92Skamil } 16371.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 16381.92Skamil 16391.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16401.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 16411.92Skamil 16421.92Skamil validate_status_signaled(status, sig, 1); 16431.92Skamil 16441.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16451.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 16461.92Skamil} 16471.92Skamil 16481.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig) \ 16491.92SkamilATF_TC(test); \ 16501.92SkamilATF_TC_HEAD(test, tc) \ 16511.92Skamil{ \ 16521.92Skamil atf_tc_set_md_var(tc, "descr", \ 16531.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16541.92Skamil "vfork(2)ed child with a masked signal"); \ 16551.92Skamil} \ 16561.92Skamil \ 16571.92SkamilATF_TC_BODY(test, tc) \ 16581.92Skamil{ \ 16591.92Skamil \ 16601.92Skamil traceme_vfork_signalmasked_crash(sig); \ 16611.92Skamil} 16621.92Skamil 16631.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP) 16641.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV) 16651.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL) 16661.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE) 16671.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS) 16681.92Skamil 16691.92Skamil/// ---------------------------------------------------------------------------- 16701.92Skamil 16711.92Skamilstatic void 16721.92Skamiltraceme_vfork_signalignored_crash(int sig) 16731.92Skamil{ 16741.92Skamil pid_t child, wpid; 16751.92Skamil#if defined(TWAIT_HAVE_STATUS) 16761.92Skamil int status; 16771.92Skamil#endif 16781.92Skamil struct sigaction sa; 16791.92Skamil 16801.92Skamil#ifndef PTRACE_ILLEGAL_ASM 16811.92Skamil if (sig == SIGILL) 16821.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 16831.92Skamil#endif 16841.92Skamil 16851.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 16861.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 16871.92Skamil if (child == 0) { 16881.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 16891.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 16901.92Skamil 16911.92Skamil memset(&sa, 0, sizeof(sa)); 16921.92Skamil sa.sa_handler = SIG_IGN; 16931.92Skamil sigemptyset(&sa.sa_mask); 16941.92Skamil 16951.92Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 16961.92Skamil 16971.92Skamil DPRINTF("Before executing a trap\n"); 16981.92Skamil switch (sig) { 16991.92Skamil case SIGTRAP: 17001.92Skamil trigger_trap(); 17011.92Skamil break; 17021.92Skamil case SIGSEGV: 17031.92Skamil trigger_segv(); 17041.92Skamil break; 17051.92Skamil case SIGILL: 17061.92Skamil trigger_ill(); 17071.92Skamil break; 17081.92Skamil case SIGFPE: 17091.92Skamil trigger_fpe(); 17101.92Skamil break; 17111.92Skamil case SIGBUS: 17121.92Skamil trigger_bus(); 17131.92Skamil break; 17141.92Skamil default: 17151.92Skamil /* NOTREACHED */ 17161.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17171.92Skamil } 17181.92Skamil 17191.92Skamil /* NOTREACHED */ 17201.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17211.92Skamil } 17221.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 17231.92Skamil 17241.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17251.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17261.92Skamil 17271.92Skamil validate_status_signaled(status, sig, 1); 17281.92Skamil 17291.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17301.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 17311.92Skamil} 17321.92Skamil 17331.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig) \ 17341.92SkamilATF_TC(test); \ 17351.92SkamilATF_TC_HEAD(test, tc) \ 17361.92Skamil{ \ 17371.92Skamil atf_tc_set_md_var(tc, "descr", \ 17381.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 17391.92Skamil "vfork(2)ed child with ignored signal"); \ 17401.92Skamil} \ 17411.92Skamil \ 17421.92SkamilATF_TC_BODY(test, tc) \ 17431.92Skamil{ \ 17441.92Skamil \ 17451.92Skamil traceme_vfork_signalignored_crash(sig); \ 17461.92Skamil} 17471.92Skamil 17481.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap, 17491.92Skamil SIGTRAP) 17501.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv, 17511.92Skamil SIGSEGV) 17521.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill, 17531.92Skamil SIGILL) 17541.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe, 17551.92Skamil SIGFPE) 17561.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus, 17571.92Skamil SIGBUS) 17581.92Skamil 17591.92Skamil/// ---------------------------------------------------------------------------- 17601.92Skamil 17611.43SkamilATF_TC(traceme_vfork_exec); 17621.43SkamilATF_TC_HEAD(traceme_vfork_exec, tc) 17631.43Skamil{ 17641.43Skamil atf_tc_set_md_var(tc, "descr", 17651.43Skamil "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed child"); 17661.43Skamil} 17671.43Skamil 17681.43SkamilATF_TC_BODY(traceme_vfork_exec, tc) 17691.43Skamil{ 17701.43Skamil const int sigval = SIGTRAP; 17711.43Skamil pid_t child, wpid; 17721.43Skamil#if defined(TWAIT_HAVE_STATUS) 17731.43Skamil int status; 17741.43Skamil#endif 17751.61Skre struct ptrace_siginfo info; 17761.43Skamil 17771.43Skamil memset(&info, 0, sizeof(info)); 17781.43Skamil 17791.43Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 17801.43Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 17811.43Skamil if (child == 0) { 17821.43Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 17831.43Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 17841.43Skamil 17851.43Skamil DPRINTF("Before calling execve(2) from child\n"); 17861.43Skamil execlp("/bin/echo", "/bin/echo", NULL); 17871.43Skamil 17881.43Skamil /* NOTREACHED */ 17891.43Skamil FORKEE_ASSERTX(0 && "Not reached"); 17901.43Skamil } 17911.43Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 17921.43Skamil 17931.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17941.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17951.43Skamil 17961.43Skamil validate_status_stopped(status, sigval); 17971.43Skamil 17981.43Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 17991.61Skre SYSCALL_REQUIRE( 18001.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 18011.43Skamil 18021.43Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 18031.43Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 18041.43Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 18051.43Skamil info.psi_siginfo.si_errno); 18061.43Skamil 18071.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 18081.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 18091.43Skamil 18101.43Skamil DPRINTF("Before resuming the child process where it left off and " 18111.43Skamil "without signal to be sent\n"); 18121.43Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 18131.43Skamil 18141.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 18151.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 18161.43Skamil 18171.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 18181.43Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 18191.43Skamil} 18201.43Skamil 18211.43Skamil/// ---------------------------------------------------------------------------- 18221.43Skamil 18231.1Skamil#if defined(TWAIT_HAVE_PID) 18241.51Skamilstatic void 18251.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored) 18261.59Skamil{ 18271.94Skamil const int sigval = SIGSTOP; 18281.59Skamil struct msg_fds parent_tracee, parent_tracer; 18291.59Skamil const int exitval = 10; 18301.59Skamil pid_t tracee, tracer, wpid; 18311.59Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 18321.59Skamil#if defined(TWAIT_HAVE_STATUS) 18331.59Skamil int status; 18341.59Skamil#endif 18351.94Skamil struct sigaction sa; 18361.59Skamil struct ptrace_siginfo info; 18371.94Skamil sigset_t intmask; 18381.94Skamil struct kinfo_proc2 kp; 18391.94Skamil size_t len = sizeof(kp); 18401.94Skamil 18411.94Skamil int name[6]; 18421.94Skamil const size_t namelen = __arraycount(name); 18431.94Skamil ki_sigset_t kp_sigmask; 18441.94Skamil ki_sigset_t kp_sigignore; 18451.61Skre 18461.71Skamil#ifndef PTRACE_ILLEGAL_ASM 18471.71Skamil if (sig == SIGILL) 18481.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 18491.71Skamil#endif 18501.71Skamil 18511.59Skamil memset(&info, 0, sizeof(info)); 18521.59Skamil 18531.94Skamil if (masked || ignored) 18541.94Skamil atf_tc_expect_fail("Unexpected sigmask reset on crash under " 18551.94Skamil "debugger"); 18561.94Skamil 18571.59Skamil DPRINTF("Spawn tracee\n"); 18581.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 18591.59Skamil tracee = atf_utils_fork(); 18601.59Skamil if (tracee == 0) { 18611.59Skamil // Wait for parent to let us crash 18621.59Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 18631.61Skre 18641.94Skamil if (masked) { 18651.94Skamil sigemptyset(&intmask); 18661.94Skamil sigaddset(&intmask, sig); 18671.94Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 18681.94Skamil } 18691.94Skamil 18701.94Skamil if (ignored) { 18711.94Skamil memset(&sa, 0, sizeof(sa)); 18721.94Skamil sa.sa_handler = SIG_IGN; 18731.94Skamil sigemptyset(&sa.sa_mask); 18741.94Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 18751.94Skamil } 18761.94Skamil 18771.94Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 18781.94Skamil FORKEE_ASSERT(raise(sigval) == 0); 18791.94Skamil 18801.59Skamil DPRINTF("Before executing a trap\n"); 18811.59Skamil switch (sig) { 18821.59Skamil case SIGTRAP: 18831.59Skamil trigger_trap(); 18841.59Skamil break; 18851.59Skamil case SIGSEGV: 18861.59Skamil trigger_segv(); 18871.59Skamil break; 18881.59Skamil case SIGILL: 18891.59Skamil trigger_ill(); 18901.59Skamil break; 18911.59Skamil case SIGFPE: 18921.59Skamil trigger_fpe(); 18931.59Skamil break; 18941.59Skamil case SIGBUS: 18951.59Skamil trigger_bus(); 18961.59Skamil break; 18971.59Skamil default: 18981.59Skamil /* NOTREACHED */ 18991.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 19001.59Skamil } 19011.59Skamil 19021.59Skamil /* NOTREACHED */ 19031.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 19041.59Skamil } 19051.59Skamil 19061.59Skamil DPRINTF("Spawn debugger\n"); 19071.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 19081.59Skamil tracer = atf_utils_fork(); 19091.59Skamil if (tracer == 0) { 19101.59Skamil /* Fork again and drop parent to reattach to PID 1 */ 19111.59Skamil tracer = atf_utils_fork(); 19121.59Skamil if (tracer != 0) 19131.61Skre _exit(exitval); 19141.59Skamil 19151.59Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 19161.59Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 19171.59Skamil 19181.59Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 19191.59Skamil FORKEE_REQUIRE_SUCCESS( 19201.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 19211.59Skamil 19221.59Skamil forkee_status_stopped(status, SIGSTOP); 19231.59Skamil 19241.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 19251.94Skamil "traced process\n"); 19261.94Skamil SYSCALL_REQUIRE( 19271.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 19281.94Skamil 19291.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 19301.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 19311.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 19321.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 19331.94Skamil 19341.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 19351.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 19361.94Skamil 19371.59Skamil /* Resume tracee with PT_CONTINUE */ 19381.59Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 19391.59Skamil 19401.59Skamil /* Inform parent that tracer has attached to tracee */ 19411.59Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 19421.59Skamil 19431.59Skamil /* Wait for parent to tell use that tracee should have exited */ 19441.59Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 19451.59Skamil 19461.59Skamil /* Wait for tracee and assert that it exited */ 19471.59Skamil FORKEE_REQUIRE_SUCCESS( 19481.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 19491.59Skamil 19501.94Skamil forkee_status_stopped(status, sigval); 19511.94Skamil 19521.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 19531.94Skamil "traced process\n"); 19541.94Skamil SYSCALL_REQUIRE( 19551.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 19561.94Skamil 19571.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 19581.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 19591.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 19601.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 19611.94Skamil 19621.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 19631.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 19641.94Skamil 19651.94Skamil name[0] = CTL_KERN, 19661.94Skamil name[1] = KERN_PROC2, 19671.94Skamil name[2] = KERN_PROC_PID; 19681.94Skamil name[3] = tracee; 19691.94Skamil name[4] = sizeof(kp); 19701.94Skamil name[5] = 1; 19711.94Skamil 19721.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 19731.94Skamil 19741.94Skamil if (masked) 19751.94Skamil kp_sigmask = kp.p_sigmask; 19761.94Skamil 19771.94Skamil if (ignored) 19781.94Skamil kp_sigignore = kp.p_sigignore; 19791.94Skamil 19801.94Skamil /* Resume tracee with PT_CONTINUE */ 19811.94Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 19821.94Skamil 19831.94Skamil /* Wait for tracee and assert that it exited */ 19841.94Skamil FORKEE_REQUIRE_SUCCESS( 19851.94Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 19861.94Skamil 19871.93Skamil forkee_status_stopped(status, sig); 19881.59Skamil 19891.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 19901.61Skre "traced process\n"); 19911.61Skre SYSCALL_REQUIRE( 19921.61Skre ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 19931.59Skamil 19941.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 19951.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 19961.61Skre "si_errno=%#x\n", info.psi_siginfo.si_signo, 19971.61Skre info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 19981.59Skamil 19991.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig); 20001.94Skamil 20011.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 20021.94Skamil 20031.94Skamil if (masked) { 20041.94Skamil DPRINTF("kp_sigmask=" 20051.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 20061.94Skamil PRIx32 "\n", 20071.94Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 20081.94Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 20091.94Skamil 20101.94Skamil DPRINTF("kp.p_sigmask=" 20111.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 20121.94Skamil PRIx32 "\n", 20131.94Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 20141.94Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 20151.94Skamil 20161.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask, 20171.94Skamil sizeof(kp_sigmask))); 20181.94Skamil } 20191.94Skamil 20201.94Skamil if (ignored) { 20211.94Skamil DPRINTF("kp_sigignore=" 20221.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 20231.94Skamil PRIx32 "\n", 20241.94Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 20251.94Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 20261.94Skamil 20271.94Skamil DPRINTF("kp.p_sigignore=" 20281.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 20291.94Skamil PRIx32 "\n", 20301.94Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 20311.94Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 20321.94Skamil 20331.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore, 20341.94Skamil sizeof(kp_sigignore))); 20351.94Skamil } 20361.94Skamil 20371.59Skamil switch (sig) { 20381.59Skamil case SIGTRAP: 20391.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 20401.59Skamil break; 20411.59Skamil case SIGSEGV: 20421.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 20431.59Skamil break; 20441.71Skamil case SIGILL: 20451.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, ILL_PRVOPC); 20461.71Skamil break; 20471.59Skamil case SIGFPE: 20481.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 20491.59Skamil break; 20501.59Skamil case SIGBUS: 20511.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 20521.59Skamil break; 20531.59Skamil } 20541.59Skamil 20551.59Skamil FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1); 20561.59Skamil DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME); 20571.93Skamil FORKEE_REQUIRE_SUCCESS( 20581.61Skre wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20591.59Skamil 20601.93Skamil forkee_status_signaled(status, SIGKILL, 0); 20611.59Skamil 20621.71Skamil /* Inform parent that tracer is exiting normally */ 20631.71Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 20641.71Skamil 20651.59Skamil DPRINTF("Before exiting of the tracer process\n"); 20661.59Skamil _exit(0 /* collect by initproc */); 20671.59Skamil } 20681.59Skamil 20691.59Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 20701.59Skamil "calling %s()\n", TWAIT_FNAME); 20711.59Skamil TWAIT_REQUIRE_SUCCESS( 20721.59Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 20731.59Skamil 20741.59Skamil validate_status_exited(status, exitval); 20751.59Skamil 20761.59Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 20771.59Skamil TWAIT_FNAME); 20781.59Skamil TWAIT_REQUIRE_SUCCESS( 20791.59Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 20801.59Skamil 20811.59Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 20821.59Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 20831.59Skamil 20841.59Skamil DPRINTF("Resume the tracee and let it crash\n"); 20851.59Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 20861.59Skamil 20871.59Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 20881.59Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 20891.59Skamil 20901.59Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 20911.59Skamil TWAIT_FNAME); 20921.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20931.59Skamil 20941.59Skamil validate_status_signaled(status, SIGKILL, 0); 20951.59Skamil 20961.71Skamil DPRINTF("Await normal exit of tracer\n"); 20971.71Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 20981.71Skamil 20991.59Skamil msg_close(&parent_tracer); 21001.59Skamil msg_close(&parent_tracee); 21011.59Skamil} 21021.59Skamil 21031.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig) \ 21041.61SkreATF_TC(test); \ 21051.61SkreATF_TC_HEAD(test, tc) \ 21061.61Skre{ \ 21071.61Skre atf_tc_set_md_var(tc, "descr", \ 21081.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 21091.94Skamil "the debuggee"); \ 21101.61Skre} \ 21111.61Skre \ 21121.61SkreATF_TC_BODY(test, tc) \ 21131.61Skre{ \ 21141.61Skre \ 21151.94Skamil unrelated_tracer_sees_crash(sig, false, false); \ 21161.59Skamil} 21171.59Skamil 21181.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP) 21191.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV) 21201.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL) 21211.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE) 21221.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS) 21231.94Skamil 21241.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig) \ 21251.94SkamilATF_TC(test); \ 21261.94SkamilATF_TC_HEAD(test, tc) \ 21271.94Skamil{ \ 21281.94Skamil atf_tc_set_md_var(tc, "descr", \ 21291.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 21301.94Skamil "the debuggee with masked signal"); \ 21311.94Skamil} \ 21321.94Skamil \ 21331.94SkamilATF_TC_BODY(test, tc) \ 21341.94Skamil{ \ 21351.94Skamil \ 21361.94Skamil unrelated_tracer_sees_crash(sig, true, false); \ 21371.94Skamil} 21381.94Skamil 21391.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 21401.94Skamil unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP) 21411.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 21421.94Skamil unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV) 21431.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 21441.94Skamil unrelated_tracer_sees_signalmasked_crash_ill, SIGILL) 21451.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 21461.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE) 21471.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 21481.94Skamil unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS) 21491.94Skamil 21501.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig) \ 21511.94SkamilATF_TC(test); \ 21521.94SkamilATF_TC_HEAD(test, tc) \ 21531.94Skamil{ \ 21541.94Skamil atf_tc_set_md_var(tc, "descr", \ 21551.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 21561.94Skamil "the debuggee with signal ignored"); \ 21571.94Skamil} \ 21581.94Skamil \ 21591.94SkamilATF_TC_BODY(test, tc) \ 21601.94Skamil{ \ 21611.94Skamil \ 21621.94Skamil unrelated_tracer_sees_crash(sig, false, true); \ 21631.94Skamil} 21641.94Skamil 21651.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 21661.94Skamil unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP) 21671.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 21681.94Skamil unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV) 21691.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 21701.94Skamil unrelated_tracer_sees_signalignored_crash_ill, SIGILL) 21711.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 21721.94Skamil unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE) 21731.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 21741.94Skamil unrelated_tracer_sees_signalignored_crash_bus, SIGBUS) 21751.59Skamil#endif 21761.59Skamil 21771.59Skamil/// ---------------------------------------------------------------------------- 21781.59Skamil 21791.59Skamil#if defined(TWAIT_HAVE_PID) 21801.59Skamilstatic void 21811.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated, 21821.67Skamil bool stopped) 21831.1Skamil{ 21841.51Skamil /* 21851.51Skamil * notimeout - disable timeout in await zombie function 21861.51Skamil * unrelated - attach from unrelated tracer reparented to initproc 21871.67Skamil * stopped - attach to a stopped process 21881.51Skamil */ 21891.1Skamil 21901.1Skamil struct msg_fds parent_tracee, parent_tracer; 21911.1Skamil const int exitval_tracee = 5; 21921.1Skamil const int exitval_tracer = 10; 21931.1Skamil pid_t tracee, tracer, wpid; 21941.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 21951.1Skamil#if defined(TWAIT_HAVE_STATUS) 21961.1Skamil int status; 21971.1Skamil#endif 21981.1Skamil 21991.67Skamil /* 22001.67Skamil * Only a subset of options are supported. 22011.67Skamil */ 22021.67Skamil ATF_REQUIRE((!notimeout && !unrelated && !stopped) || 22031.67Skamil (!notimeout && unrelated && !stopped) || 22041.67Skamil (notimeout && !unrelated && !stopped) || 22051.67Skamil (!notimeout && unrelated && stopped)); 22061.67Skamil 22071.13Schristos DPRINTF("Spawn tracee\n"); 22081.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 22091.1Skamil tracee = atf_utils_fork(); 22101.1Skamil if (tracee == 0) { 22111.67Skamil if (stopped) { 22121.67Skamil DPRINTF("Stop self PID %d\n", getpid()); 22131.67Skamil raise(SIGSTOP); 22141.67Skamil } 22151.67Skamil 22161.1Skamil // Wait for parent to let us exit 22171.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 22181.1Skamil _exit(exitval_tracee); 22191.1Skamil } 22201.1Skamil 22211.13Schristos DPRINTF("Spawn debugger\n"); 22221.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 22231.1Skamil tracer = atf_utils_fork(); 22241.1Skamil if (tracer == 0) { 22251.51Skamil if(unrelated) { 22261.51Skamil /* Fork again and drop parent to reattach to PID 1 */ 22271.51Skamil tracer = atf_utils_fork(); 22281.51Skamil if (tracer != 0) 22291.51Skamil _exit(exitval_tracer); 22301.51Skamil } 22311.51Skamil 22321.67Skamil if (stopped) { 22331.67Skamil DPRINTF("Await for a stopped parent PID %d\n", tracee); 22341.67Skamil await_stopped(tracee); 22351.67Skamil } 22361.67Skamil 22371.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 22381.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 22391.1Skamil 22401.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 22411.1Skamil FORKEE_REQUIRE_SUCCESS( 22421.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22431.1Skamil 22441.1Skamil forkee_status_stopped(status, SIGSTOP); 22451.1Skamil 22461.1Skamil /* Resume tracee with PT_CONTINUE */ 22471.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 22481.1Skamil 22491.1Skamil /* Inform parent that tracer has attached to tracee */ 22501.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 22511.1Skamil 22521.1Skamil /* Wait for parent to tell use that tracee should have exited */ 22531.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 22541.1Skamil 22551.1Skamil /* Wait for tracee and assert that it exited */ 22561.1Skamil FORKEE_REQUIRE_SUCCESS( 22571.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22581.1Skamil 22591.1Skamil forkee_status_exited(status, exitval_tracee); 22601.13Schristos DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee); 22611.1Skamil 22621.13Schristos DPRINTF("Before exiting of the tracer process\n"); 22631.51Skamil _exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer); 22641.51Skamil } 22651.51Skamil 22661.51Skamil if (unrelated) { 22671.51Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 22681.51Skamil "calling %s()\n", TWAIT_FNAME); 22691.51Skamil TWAIT_REQUIRE_SUCCESS( 22701.51Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 22711.51Skamil 22721.51Skamil validate_status_exited(status, exitval_tracer); 22731.51Skamil 22741.51Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 22751.51Skamil TWAIT_FNAME); 22761.51Skamil TWAIT_REQUIRE_SUCCESS( 22771.51Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 22781.1Skamil } 22791.1Skamil 22801.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 22811.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 22821.1Skamil 22831.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 22841.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 22851.1Skamil 22861.13Schristos DPRINTF("Detect that tracee is zombie\n"); 22871.51Skamil if (notimeout) 22881.26Skamil await_zombie_raw(tracee, 0); 22891.26Skamil else 22901.26Skamil await_zombie(tracee); 22911.1Skamil 22921.13Schristos DPRINTF("Assert that there is no status about tracee %d - " 22931.1Skamil "Tracer must detect zombie first - calling %s()\n", tracee, 22941.1Skamil TWAIT_FNAME); 22951.1Skamil TWAIT_REQUIRE_SUCCESS( 22961.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 22971.1Skamil 22981.51Skamil if (unrelated) { 22991.51Skamil DPRINTF("Resume the tracer and let it detect exited tracee\n"); 23001.51Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 23011.51Skamil } else { 23021.51Skamil DPRINTF("Tell the tracer child should have exited\n"); 23031.51Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 23041.51Skamil DPRINTF("Wait for tracer to finish its job and exit - calling " 23051.59Skamil "%s()\n", TWAIT_FNAME); 23061.51Skamil 23071.51Skamil DPRINTF("Wait from tracer child to complete waiting for " 23081.59Skamil "tracee\n"); 23091.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 23101.51Skamil tracer); 23111.1Skamil 23121.51Skamil validate_status_exited(status, exitval_tracer); 23131.51Skamil } 23141.1Skamil 23151.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 23161.1Skamil TWAIT_FNAME); 23171.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23181.1Skamil 23191.1Skamil validate_status_exited(status, exitval_tracee); 23201.1Skamil 23211.1Skamil msg_close(&parent_tracer); 23221.1Skamil msg_close(&parent_tracee); 23231.1Skamil} 23241.26Skamil 23251.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent); 23261.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc) 23271.51Skamil{ 23281.51Skamil atf_tc_set_md_var(tc, "descr", 23291.51Skamil "Assert that tracer sees process termination before the parent"); 23301.51Skamil} 23311.51Skamil 23321.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc) 23331.26Skamil{ 23341.26Skamil 23351.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, false, false); 23361.26Skamil} 23371.26Skamil 23381.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates); 23391.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc) 23401.1Skamil{ 23411.1Skamil atf_tc_set_md_var(tc, "descr", 23421.51Skamil "Assert that await_zombie() in attach1 always finds a single " 23431.51Skamil "process and no other error is reported"); 23441.1Skamil} 23451.1Skamil 23461.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc) 23471.1Skamil{ 23481.51Skamil time_t start, end; 23491.51Skamil double diff; 23501.51Skamil unsigned long N = 0; 23511.1Skamil 23521.51Skamil /* 23531.51Skamil * Reuse this test with tracer_sees_terminaton_before_the_parent_raw(). 23541.51Skamil * This test body isn't specific to this race, however it's just good 23551.51Skamil * enough for this purposes, no need to invent a dedicated code flow. 23561.51Skamil */ 23571.1Skamil 23581.51Skamil start = time(NULL); 23591.51Skamil while (true) { 23601.51Skamil DPRINTF("Step: %lu\n", N); 23611.67Skamil tracer_sees_terminaton_before_the_parent_raw(true, false, 23621.67Skamil false); 23631.51Skamil end = time(NULL); 23641.51Skamil diff = difftime(end, start); 23651.51Skamil if (diff >= 5.0) 23661.51Skamil break; 23671.51Skamil ++N; 23681.1Skamil } 23691.51Skamil DPRINTF("Iterations: %lu\n", N); 23701.51Skamil} 23711.1Skamil 23721.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent); 23731.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc) 23741.51Skamil{ 23751.51Skamil atf_tc_set_md_var(tc, "descr", 23761.51Skamil "Assert that tracer sees process termination before the parent"); 23771.51Skamil} 23781.1Skamil 23791.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc) 23801.51Skamil{ 23811.1Skamil 23821.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, false); 23831.67Skamil} 23841.67Skamil 23851.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process); 23861.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc) 23871.67Skamil{ 23881.67Skamil atf_tc_set_md_var(tc, "descr", 23891.67Skamil "Assert that tracer can attach to an unrelated stopped process"); 23901.67Skamil} 23911.67Skamil 23921.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc) 23931.67Skamil{ 23941.67Skamil 23951.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, true); 23961.1Skamil} 23971.1Skamil#endif 23981.1Skamil 23991.51Skamil/// ---------------------------------------------------------------------------- 24001.51Skamil 24011.66Skamilstatic void 24021.66Skamilparent_attach_to_its_child(bool stopped) 24031.1Skamil{ 24041.1Skamil struct msg_fds parent_tracee; 24051.1Skamil const int exitval_tracee = 5; 24061.1Skamil pid_t tracee, wpid; 24071.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 24081.1Skamil#if defined(TWAIT_HAVE_STATUS) 24091.1Skamil int status; 24101.1Skamil#endif 24111.1Skamil 24121.13Schristos DPRINTF("Spawn tracee\n"); 24131.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 24141.1Skamil tracee = atf_utils_fork(); 24151.1Skamil if (tracee == 0) { 24161.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 24171.13Schristos DPRINTF("Parent should now attach to tracee\n"); 24181.1Skamil 24191.66Skamil if (stopped) { 24201.66Skamil DPRINTF("Stop self PID %d\n", getpid()); 24211.66Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 24221.66Skamil } 24231.66Skamil 24241.1Skamil CHILD_FROM_PARENT("Message 2", parent_tracee, msg); 24251.1Skamil /* Wait for message from the parent */ 24261.1Skamil _exit(exitval_tracee); 24271.1Skamil } 24281.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 24291.57Skamil 24301.66Skamil if (stopped) { 24311.66Skamil DPRINTF("Await for a stopped tracee PID %d\n", tracee); 24321.66Skamil await_stopped(tracee); 24331.66Skamil } 24341.66Skamil 24351.13Schristos DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee); 24361.13Schristos SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 24371.1Skamil 24381.13Schristos DPRINTF("Wait for the stopped tracee process with %s()\n", 24391.1Skamil TWAIT_FNAME); 24401.1Skamil TWAIT_REQUIRE_SUCCESS( 24411.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24421.1Skamil 24431.1Skamil validate_status_stopped(status, SIGSTOP); 24441.1Skamil 24451.13Schristos DPRINTF("Resume tracee with PT_CONTINUE\n"); 24461.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 24471.1Skamil 24481.13Schristos DPRINTF("Let the tracee exit now\n"); 24491.1Skamil PARENT_TO_CHILD("Message 2", parent_tracee, msg); 24501.1Skamil 24511.13Schristos DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME); 24521.1Skamil TWAIT_REQUIRE_SUCCESS( 24531.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24541.1Skamil 24551.1Skamil validate_status_exited(status, exitval_tracee); 24561.1Skamil 24571.13Schristos DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME); 24581.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 24591.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0)); 24601.1Skamil 24611.1Skamil msg_close(&parent_tracee); 24621.1Skamil} 24631.1Skamil 24641.66SkamilATF_TC(parent_attach_to_its_child); 24651.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc) 24661.66Skamil{ 24671.66Skamil atf_tc_set_md_var(tc, "descr", 24681.66Skamil "Assert that tracer parent can PT_ATTACH to its child"); 24691.66Skamil} 24701.66Skamil 24711.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc) 24721.66Skamil{ 24731.66Skamil 24741.66Skamil parent_attach_to_its_child(false); 24751.66Skamil} 24761.66Skamil 24771.66SkamilATF_TC(parent_attach_to_its_stopped_child); 24781.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc) 24791.66Skamil{ 24801.66Skamil atf_tc_set_md_var(tc, "descr", 24811.66Skamil "Assert that tracer parent can PT_ATTACH to its stopped child"); 24821.66Skamil} 24831.66Skamil 24841.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc) 24851.66Skamil{ 24861.66Skamil 24871.66Skamil parent_attach_to_its_child(true); 24881.66Skamil} 24891.66Skamil 24901.51Skamil/// ---------------------------------------------------------------------------- 24911.51Skamil 24921.65Skamilstatic void 24931.65Skamilchild_attach_to_its_parent(bool stopped) 24941.1Skamil{ 24951.1Skamil struct msg_fds parent_tracee; 24961.1Skamil const int exitval_tracer = 5; 24971.1Skamil pid_t tracer, wpid; 24981.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 24991.1Skamil#if defined(TWAIT_HAVE_STATUS) 25001.1Skamil int status; 25011.1Skamil#endif 25021.1Skamil 25031.13Schristos DPRINTF("Spawn tracer\n"); 25041.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 25051.1Skamil tracer = atf_utils_fork(); 25061.1Skamil if (tracer == 0) { 25071.1Skamil /* Wait for message from the parent */ 25081.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 25091.1Skamil 25101.65Skamil if (stopped) { 25111.65Skamil DPRINTF("Await for a stopped parent PID %d\n", 25121.65Skamil getppid()); 25131.65Skamil await_stopped(getppid()); 25141.65Skamil } 25151.65Skamil 25161.13Schristos DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n", 25171.1Skamil getppid()); 25181.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1); 25191.1Skamil 25201.13Schristos DPRINTF("Wait for the stopped parent process with %s()\n", 25211.1Skamil TWAIT_FNAME); 25221.1Skamil FORKEE_REQUIRE_SUCCESS( 25231.1Skamil wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid()); 25241.1Skamil 25251.1Skamil forkee_status_stopped(status, SIGSTOP); 25261.1Skamil 25271.13Schristos DPRINTF("Resume parent with PT_DETACH\n"); 25281.1Skamil FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0) 25291.1Skamil != -1); 25301.1Skamil 25311.1Skamil /* Tell parent we are ready */ 25321.1Skamil CHILD_TO_PARENT("Message 1", parent_tracee, msg); 25331.1Skamil 25341.1Skamil _exit(exitval_tracer); 25351.1Skamil } 25361.1Skamil 25371.13Schristos DPRINTF("Wait for the tracer to become ready\n"); 25381.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 25391.65Skamil 25401.65Skamil if (stopped) { 25411.65Skamil DPRINTF("Stop self PID %d\n", getpid()); 25421.65Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 25431.65Skamil } 25441.65Skamil 25451.13Schristos DPRINTF("Allow the tracer to exit now\n"); 25461.1Skamil PARENT_FROM_CHILD("Message 1", parent_tracee, msg); 25471.1Skamil 25481.13Schristos DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME); 25491.1Skamil TWAIT_REQUIRE_SUCCESS( 25501.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 25511.1Skamil 25521.1Skamil validate_status_exited(status, exitval_tracer); 25531.1Skamil 25541.13Schristos DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME); 25551.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 25561.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0)); 25571.1Skamil 25581.1Skamil msg_close(&parent_tracee); 25591.1Skamil} 25601.1Skamil 25611.65SkamilATF_TC(child_attach_to_its_parent); 25621.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc) 25631.65Skamil{ 25641.65Skamil atf_tc_set_md_var(tc, "descr", 25651.65Skamil "Assert that tracer child can PT_ATTACH to its parent"); 25661.65Skamil} 25671.65Skamil 25681.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc) 25691.65Skamil{ 25701.65Skamil 25711.65Skamil child_attach_to_its_parent(false); 25721.65Skamil} 25731.65Skamil 25741.65SkamilATF_TC(child_attach_to_its_stopped_parent); 25751.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc) 25761.65Skamil{ 25771.65Skamil atf_tc_set_md_var(tc, "descr", 25781.65Skamil "Assert that tracer child can PT_ATTACH to its stopped parent"); 25791.65Skamil} 25801.65Skamil 25811.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc) 25821.65Skamil{ 25831.65Skamil /* 25841.65Skamil * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as 25851.65Skamil * this causes a pipe (established from atf-run) to be broken. 25861.65Skamil * atf-run uses this mechanism to monitor whether a test is alive. 25871.65Skamil * 25881.65Skamil * As a workaround spawn this test as a subprocess. 25891.65Skamil */ 25901.65Skamil 25911.65Skamil const int exitval = 15; 25921.65Skamil pid_t child, wpid; 25931.65Skamil#if defined(TWAIT_HAVE_STATUS) 25941.65Skamil int status; 25951.65Skamil#endif 25961.65Skamil 25971.65Skamil SYSCALL_REQUIRE((child = fork()) != -1); 25981.65Skamil if (child == 0) { 25991.65Skamil child_attach_to_its_parent(true); 26001.65Skamil _exit(exitval); 26011.65Skamil } else { 26021.65Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 26031.65Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 26041.65Skamil 26051.65Skamil validate_status_exited(status, exitval); 26061.65Skamil 26071.65Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 26081.65Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 26091.65Skamil } 26101.65Skamil} 26111.65Skamil 26121.51Skamil/// ---------------------------------------------------------------------------- 26131.51Skamil 26141.1Skamil#if defined(TWAIT_HAVE_PID) 26151.1Skamil 26161.51Skamilenum tracee_sees_its_original_parent_type { 26171.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 26181.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 26191.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS 26201.51Skamil}; 26211.51Skamil 26221.51Skamilstatic void 26231.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type) 26241.1Skamil{ 26251.1Skamil struct msg_fds parent_tracer, parent_tracee; 26261.1Skamil const int exitval_tracee = 5; 26271.1Skamil const int exitval_tracer = 10; 26281.1Skamil pid_t parent, tracee, tracer, wpid; 26291.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 26301.1Skamil#if defined(TWAIT_HAVE_STATUS) 26311.1Skamil int status; 26321.1Skamil#endif 26331.51Skamil /* sysctl(3) - kinfo_proc2 */ 26341.51Skamil int name[CTL_MAXNAME]; 26351.51Skamil struct kinfo_proc2 kp; 26361.51Skamil size_t len = sizeof(kp); 26371.51Skamil unsigned int namelen; 26381.51Skamil 26391.51Skamil /* procfs - status */ 26401.51Skamil FILE *fp; 26411.51Skamil struct stat st; 26421.51Skamil const char *fname = "/proc/curproc/status"; 26431.51Skamil char s_executable[MAXPATHLEN]; 26441.51Skamil int s_pid, s_ppid; 26451.51Skamil int rv; 26461.51Skamil 26471.51Skamil if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) { 26481.61Skre SYSCALL_REQUIRE( 26491.61Skre (rv = stat(fname, &st)) == 0 || (errno == ENOENT)); 26501.61Skre if (rv != 0) 26511.51Skamil atf_tc_skip("/proc/curproc/status not found"); 26521.51Skamil } 26531.1Skamil 26541.13Schristos DPRINTF("Spawn tracee\n"); 26551.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 26561.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 26571.1Skamil tracee = atf_utils_fork(); 26581.1Skamil if (tracee == 0) { 26591.1Skamil parent = getppid(); 26601.1Skamil 26611.1Skamil /* Emit message to the parent */ 26621.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 26631.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 26641.1Skamil 26651.51Skamil switch (type) { 26661.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID: 26671.51Skamil FORKEE_ASSERT_EQ(parent, getppid()); 26681.51Skamil break; 26691.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2: 26701.51Skamil namelen = 0; 26711.51Skamil name[namelen++] = CTL_KERN; 26721.51Skamil name[namelen++] = KERN_PROC2; 26731.51Skamil name[namelen++] = KERN_PROC_PID; 26741.51Skamil name[namelen++] = getpid(); 26751.51Skamil name[namelen++] = len; 26761.51Skamil name[namelen++] = 1; 26771.51Skamil 26781.61Skre FORKEE_ASSERT_EQ( 26791.61Skre sysctl(name, namelen, &kp, &len, NULL, 0), 0); 26801.51Skamil FORKEE_ASSERT_EQ(parent, kp.p_ppid); 26811.51Skamil break; 26821.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS: 26831.51Skamil /* 26841.51Skamil * Format: 26851.51Skamil * EXECUTABLE PID PPID ... 26861.51Skamil */ 26871.51Skamil FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL); 26881.51Skamil fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid); 26891.51Skamil FORKEE_ASSERT_EQ(fclose(fp), 0); 26901.51Skamil FORKEE_ASSERT_EQ(parent, s_ppid); 26911.51Skamil break; 26921.51Skamil } 26931.1Skamil 26941.1Skamil _exit(exitval_tracee); 26951.1Skamil } 26961.13Schristos DPRINTF("Wait for child to record its parent identifier (pid)\n"); 26971.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 26981.1Skamil 26991.13Schristos DPRINTF("Spawn debugger\n"); 27001.1Skamil tracer = atf_utils_fork(); 27011.1Skamil if (tracer == 0) { 27021.1Skamil /* No IPC to communicate with the child */ 27031.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 27041.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 27051.1Skamil 27061.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 27071.1Skamil FORKEE_REQUIRE_SUCCESS( 27081.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 27091.1Skamil 27101.1Skamil forkee_status_stopped(status, SIGSTOP); 27111.1Skamil 27121.1Skamil /* Resume tracee with PT_CONTINUE */ 27131.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 27141.1Skamil 27151.1Skamil /* Inform parent that tracer has attached to tracee */ 27161.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 27171.1Skamil 27181.1Skamil /* Wait for parent to tell use that tracee should have exited */ 27191.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 27201.1Skamil 27211.1Skamil /* Wait for tracee and assert that it exited */ 27221.1Skamil FORKEE_REQUIRE_SUCCESS( 27231.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 27241.1Skamil 27251.1Skamil forkee_status_exited(status, exitval_tracee); 27261.1Skamil 27271.13Schristos DPRINTF("Before exiting of the tracer process\n"); 27281.1Skamil _exit(exitval_tracer); 27291.1Skamil } 27301.1Skamil 27311.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 27321.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 27331.1Skamil 27341.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 27351.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 27361.1Skamil 27371.13Schristos DPRINTF("Detect that tracee is zombie\n"); 27381.1Skamil await_zombie(tracee); 27391.1Skamil 27401.13Schristos DPRINTF("Assert that there is no status about tracee - " 27411.1Skamil "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME); 27421.1Skamil TWAIT_REQUIRE_SUCCESS( 27431.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 27441.1Skamil 27451.13Schristos DPRINTF("Tell the tracer child should have exited\n"); 27461.1Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 27471.1Skamil 27481.13Schristos DPRINTF("Wait from tracer child to complete waiting for tracee\n"); 27491.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 27501.1Skamil tracer); 27511.1Skamil 27521.1Skamil validate_status_exited(status, exitval_tracer); 27531.1Skamil 27541.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 27551.1Skamil TWAIT_FNAME); 27561.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 27571.1Skamil tracee); 27581.1Skamil 27591.1Skamil validate_status_exited(status, exitval_tracee); 27601.1Skamil 27611.1Skamil msg_close(&parent_tracer); 27621.1Skamil msg_close(&parent_tracee); 27631.1Skamil} 27641.1Skamil 27651.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr) \ 27661.61SkreATF_TC(test); \ 27671.61SkreATF_TC_HEAD(test, tc) \ 27681.61Skre{ \ 27691.61Skre atf_tc_set_md_var(tc, "descr", \ 27701.61Skre "Assert that tracee sees its original parent when being traced " \ 27711.61Skre "(check " descr ")"); \ 27721.61Skre} \ 27731.61Skre \ 27741.61SkreATF_TC_BODY(test, tc) \ 27751.61Skre{ \ 27761.61Skre \ 27771.61Skre tracee_sees_its_original_parent(type); \ 27781.1Skamil} 27791.1Skamil 27801.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 27811.51Skamil tracee_sees_its_original_parent_getppid, 27821.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 27831.51Skamil "getppid(2)"); 27841.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 27851.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2, 27861.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 27871.51Skamil "sysctl(3) and kinfo_proc2"); 27881.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 27891.51Skamil tracee_sees_its_original_parent_procfs_status, 27901.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS, 27911.51Skamil "the status file in procfs"); 27921.1Skamil#endif 27931.1Skamil 27941.51Skamil/// ---------------------------------------------------------------------------- 27951.1Skamil 27961.53Skamilstatic void 27971.53Skamileventmask_preserved(int event) 27981.1Skamil{ 27991.1Skamil const int exitval = 5; 28001.1Skamil const int sigval = SIGSTOP; 28011.1Skamil pid_t child, wpid; 28021.1Skamil#if defined(TWAIT_HAVE_STATUS) 28031.1Skamil int status; 28041.1Skamil#endif 28051.1Skamil ptrace_event_t set_event, get_event; 28061.1Skamil const int len = sizeof(ptrace_event_t); 28071.1Skamil 28081.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 28091.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 28101.1Skamil if (child == 0) { 28111.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 28121.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 28131.1Skamil 28141.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 28151.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 28161.1Skamil 28171.13Schristos DPRINTF("Before exiting of the child process\n"); 28181.1Skamil _exit(exitval); 28191.1Skamil } 28201.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 28211.1Skamil 28221.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 28231.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 28241.1Skamil 28251.1Skamil validate_status_stopped(status, sigval); 28261.1Skamil 28271.53Skamil set_event.pe_set_event = event; 28281.61Skre SYSCALL_REQUIRE( 28291.61Skre ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); 28301.61Skre SYSCALL_REQUIRE( 28311.61Skre ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); 28321.1Skamil ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); 28331.1Skamil 28341.13Schristos DPRINTF("Before resuming the child process where it left off and " 28351.1Skamil "without signal to be sent\n"); 28361.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 28371.1Skamil 28381.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 28391.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 28401.1Skamil 28411.1Skamil validate_status_exited(status, exitval); 28421.1Skamil 28431.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 28441.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 28451.1Skamil} 28461.1Skamil 28471.61Skre#define EVENTMASK_PRESERVED(test, event) \ 28481.61SkreATF_TC(test); \ 28491.61SkreATF_TC_HEAD(test, tc) \ 28501.61Skre{ \ 28511.61Skre atf_tc_set_md_var(tc, "descr", \ 28521.61Skre "Verify that eventmask " #event " is preserved"); \ 28531.61Skre} \ 28541.61Skre \ 28551.61SkreATF_TC_BODY(test, tc) \ 28561.61Skre{ \ 28571.61Skre \ 28581.61Skre eventmask_preserved(event); \ 28591.1Skamil} 28601.1Skamil 28611.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0) 28621.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK) 28631.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK) 28641.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE) 28651.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE) 28661.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT) 28671.1Skamil 28681.53Skamil/// ---------------------------------------------------------------------------- 28691.1Skamil 28701.28Skamilstatic void 28711.32Skamilfork_body(pid_t (*fn)(void), bool trackfork, bool trackvfork, 28721.61Skre bool trackvforkdone, bool detachchild, bool detachparent) 28731.1Skamil{ 28741.1Skamil const int exitval = 5; 28751.1Skamil const int exitval2 = 15; 28761.1Skamil const int sigval = SIGSTOP; 28771.31Skamil pid_t child, child2 = 0, wpid; 28781.1Skamil#if defined(TWAIT_HAVE_STATUS) 28791.1Skamil int status; 28801.1Skamil#endif 28811.1Skamil ptrace_state_t state; 28821.1Skamil const int slen = sizeof(state); 28831.1Skamil ptrace_event_t event; 28841.1Skamil const int elen = sizeof(event); 28851.1Skamil 28861.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 28871.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 28881.1Skamil if (child == 0) { 28891.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 28901.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 28911.1Skamil 28921.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 28931.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 28941.1Skamil 28951.30Skamil FORKEE_ASSERT((child2 = (fn)()) != -1); 28961.1Skamil 28971.1Skamil if (child2 == 0) 28981.1Skamil _exit(exitval2); 28991.1Skamil 29001.1Skamil FORKEE_REQUIRE_SUCCESS 29011.1Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 29021.1Skamil 29031.1Skamil forkee_status_exited(status, exitval2); 29041.1Skamil 29051.13Schristos DPRINTF("Before exiting of the child process\n"); 29061.1Skamil _exit(exitval); 29071.1Skamil } 29081.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 29091.1Skamil 29101.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29111.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29121.1Skamil 29131.1Skamil validate_status_stopped(status, sigval); 29141.1Skamil 29151.30Skamil DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n", 29161.61Skre trackfork ? "|PTRACE_FORK" : "", 29171.61Skre trackvfork ? "|PTRACE_VFORK" : "", 29181.61Skre trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child); 29191.30Skamil event.pe_set_event = 0; 29201.30Skamil if (trackfork) 29211.30Skamil event.pe_set_event |= PTRACE_FORK; 29221.30Skamil if (trackvfork) 29231.30Skamil event.pe_set_event |= PTRACE_VFORK; 29241.30Skamil if (trackvforkdone) 29251.30Skamil event.pe_set_event |= PTRACE_VFORK_DONE; 29261.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 29271.1Skamil 29281.13Schristos DPRINTF("Before resuming the child process where it left off and " 29291.1Skamil "without signal to be sent\n"); 29301.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 29311.1Skamil 29321.29Skamil#if defined(TWAIT_HAVE_PID) 29331.31Skamil if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) { 29341.29Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 29351.61Skre child); 29361.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 29371.61Skre child); 29381.1Skamil 29391.29Skamil validate_status_stopped(status, SIGTRAP); 29401.1Skamil 29411.61Skre SYSCALL_REQUIRE( 29421.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 29431.31Skamil if (trackfork && fn == fork) { 29441.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 29451.30Skamil PTRACE_FORK); 29461.30Skamil } 29471.31Skamil if (trackvfork && fn == vfork) { 29481.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 29491.30Skamil PTRACE_VFORK); 29501.30Skamil } 29511.29Skamil 29521.29Skamil child2 = state.pe_other_pid; 29531.30Skamil DPRINTF("Reported ptrace event with forkee %d\n", child2); 29541.29Skamil 29551.29Skamil DPRINTF("Before calling %s() for the forkee %d of the child " 29561.61Skre "%d\n", TWAIT_FNAME, child2, child); 29571.29Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 29581.29Skamil child2); 29591.1Skamil 29601.29Skamil validate_status_stopped(status, SIGTRAP); 29611.1Skamil 29621.61Skre SYSCALL_REQUIRE( 29631.61Skre ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 29641.31Skamil if (trackfork && fn == fork) { 29651.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK, 29661.30Skamil PTRACE_FORK); 29671.30Skamil } 29681.31Skamil if (trackvfork && fn == vfork) { 29691.30Skamil ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK, 29701.30Skamil PTRACE_VFORK); 29711.30Skamil } 29721.30Skamil 29731.29Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 29741.29Skamil 29751.29Skamil DPRINTF("Before resuming the forkee process where it left off " 29761.29Skamil "and without signal to be sent\n"); 29771.61Skre SYSCALL_REQUIRE( 29781.61Skre ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 29791.29Skamil 29801.29Skamil DPRINTF("Before resuming the child process where it left off " 29811.61Skre "and without signal to be sent\n"); 29821.29Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 29831.30Skamil } 29841.30Skamil#endif 29851.30Skamil 29861.31Skamil if (trackvforkdone && fn == vfork) { 29871.30Skamil DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME, 29881.61Skre child); 29891.61Skre TWAIT_REQUIRE_SUCCESS( 29901.61Skre wpid = TWAIT_GENERIC(child, &status, 0), child); 29911.30Skamil 29921.30Skamil validate_status_stopped(status, SIGTRAP); 29931.30Skamil 29941.61Skre SYSCALL_REQUIRE( 29951.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 29961.30Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 29971.30Skamil 29981.30Skamil child2 = state.pe_other_pid; 29991.30Skamil DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", 30001.61Skre child2); 30011.30Skamil 30021.30Skamil DPRINTF("Before resuming the child process where it left off " 30031.61Skre "and without signal to be sent\n"); 30041.30Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 30051.30Skamil } 30061.29Skamil 30071.30Skamil#if defined(TWAIT_HAVE_PID) 30081.31Skamil if ((trackfork && fn == fork) || (trackvfork && fn == vfork)) { 30091.29Skamil DPRINTF("Before calling %s() for the forkee - expected exited" 30101.61Skre "\n", TWAIT_FNAME); 30111.61Skre TWAIT_REQUIRE_SUCCESS( 30121.61Skre wpid = TWAIT_GENERIC(child2, &status, 0), child2); 30131.29Skamil 30141.29Skamil validate_status_exited(status, exitval2); 30151.29Skamil 30161.29Skamil DPRINTF("Before calling %s() for the forkee - expected no " 30171.61Skre "process\n", TWAIT_FNAME); 30181.29Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 30191.29Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 30201.29Skamil } 30211.29Skamil#endif 30221.1Skamil 30231.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 30241.1Skamil "SIGCHLD\n", TWAIT_FNAME); 30251.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 30261.1Skamil 30271.1Skamil validate_status_stopped(status, SIGCHLD); 30281.1Skamil 30291.13Schristos DPRINTF("Before resuming the child process where it left off and " 30301.1Skamil "without signal to be sent\n"); 30311.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 30321.1Skamil 30331.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 30341.1Skamil TWAIT_FNAME); 30351.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 30361.1Skamil 30371.1Skamil validate_status_exited(status, exitval); 30381.1Skamil 30391.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 30401.1Skamil TWAIT_FNAME); 30411.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 30421.1Skamil} 30431.28Skamil 30441.61Skre#define FORK_TEST(name,descr,fun,tfork,tvfork,tvforkdone,detchild,detparent) \ 30451.61SkreATF_TC(name); \ 30461.61SkreATF_TC_HEAD(name, tc) \ 30471.61Skre{ \ 30481.61Skre atf_tc_set_md_var(tc, "descr", descr); \ 30491.61Skre} \ 30501.61Skre \ 30511.61SkreATF_TC_BODY(name, tc) \ 30521.61Skre{ \ 30531.61Skre \ 30541.61Skre fork_body(fun, tfork, tvfork, tvforkdone, detchild, detparent); \ 30551.32Skamil} 30561.32Skamil 30571.32Skamil#define F false 30581.32Skamil#define T true 30591.32Skamil 30601.32Skamil#define F_IF__0(x) 30611.32Skamil#define F_IF__1(x) x 30621.32Skamil#define F_IF__(x,y) F_IF__ ## x (y) 30631.32Skamil#define F_IF_(x,y) F_IF__(x,y) 30641.32Skamil#define F_IF(x,y) F_IF_(x,y) 30651.32Skamil 30661.61Skre#define DSCR(function,forkbit,vforkbit,vforkdonebit,dchildbit,dparentbit) \ 30671.61Skre "Verify " #function "(2) called with 0" \ 30681.61Skre F_IF(forkbit,"|PTRACE_FORK") \ 30691.61Skre F_IF(vforkbit,"|PTRACE_VFORK") \ 30701.61Skre F_IF(vforkdonebit,"|PTRACE_VFORK_DONE") \ 30711.61Skre " in EVENT_MASK." \ 30721.61Skre F_IF(dchildbit," Detach child in this test.") \ 30731.61Skre F_IF(dparentbit," Detach parent in this test.") 30741.1Skamil 30751.32SkamilFORK_TEST(fork1, DSCR(fork,0,0,0,0,0), fork, F, F, F, F, F) 30761.31Skamil#if defined(TWAIT_HAVE_PID) 30771.32SkamilFORK_TEST(fork2, DSCR(fork,1,0,0,0,0), fork, T, F, F, F, F) 30781.32SkamilFORK_TEST(fork3, DSCR(fork,0,1,0,0,0), fork, F, T, F, F, F) 30791.32SkamilFORK_TEST(fork4, DSCR(fork,1,1,0,0,0), fork, T, T, F, F, F) 30801.31Skamil#endif 30811.32SkamilFORK_TEST(fork5, DSCR(fork,0,0,1,0,0), fork, F, F, T, F, F) 30821.31Skamil#if defined(TWAIT_HAVE_PID) 30831.32SkamilFORK_TEST(fork6, DSCR(fork,1,0,1,0,0), fork, T, F, T, F, F) 30841.32SkamilFORK_TEST(fork7, DSCR(fork,0,1,1,0,0), fork, F, T, T, F, F) 30851.32SkamilFORK_TEST(fork8, DSCR(fork,1,1,1,0,0), fork, T, T, T, F, F) 30861.31Skamil#endif 30871.1Skamil 30881.32SkamilFORK_TEST(vfork1, DSCR(vfork,0,0,0,0,0), vfork, F, F, F, F, F) 30891.31Skamil#if defined(TWAIT_HAVE_PID) 30901.32SkamilFORK_TEST(vfork2, DSCR(vfork,1,0,0,0,0), vfork, T, F, F, F, F) 30911.32SkamilFORK_TEST(vfork3, DSCR(vfork,0,1,0,0,0), vfork, F, T, F, F, F) 30921.32SkamilFORK_TEST(vfork4, DSCR(vfork,1,1,0,0,0), vfork, T, T, F, F, F) 30931.31Skamil#endif 30941.32SkamilFORK_TEST(vfork5, DSCR(vfork,0,0,1,0,0), vfork, F, F, T, F, F) 30951.31Skamil#if defined(TWAIT_HAVE_PID) 30961.32SkamilFORK_TEST(vfork6, DSCR(vfork,1,0,1,0,0), vfork, T, F, T, F, F) 30971.32SkamilFORK_TEST(vfork7, DSCR(vfork,0,1,1,0,0), vfork, F, T, T, F, F) 30981.32SkamilFORK_TEST(vfork8, DSCR(vfork,1,1,1,0,0), vfork, T, T, T, F, F) 30991.31Skamil#endif 31001.31Skamil 31011.54Skamil/// ---------------------------------------------------------------------------- 31021.31Skamil 31031.54Skamilenum bytes_transfer_type { 31041.54Skamil BYTES_TRANSFER_DATA, 31051.54Skamil BYTES_TRANSFER_DATAIO, 31061.54Skamil BYTES_TRANSFER_TEXT, 31071.54Skamil BYTES_TRANSFER_TEXTIO, 31081.54Skamil BYTES_TRANSFER_AUXV 31091.54Skamil}; 31101.31Skamil 31111.54Skamilstatic int __used 31121.54Skamilbytes_transfer_dummy(int a, int b, int c, int d) 31131.54Skamil{ 31141.54Skamil int e, f, g, h; 31151.1Skamil 31161.54Skamil a *= 4; 31171.54Skamil b += 3; 31181.54Skamil c -= 2; 31191.54Skamil d /= 1; 31201.1Skamil 31211.54Skamil e = strtol("10", NULL, 10); 31221.54Skamil f = strtol("20", NULL, 10); 31231.54Skamil g = strtol("30", NULL, 10); 31241.54Skamil h = strtol("40", NULL, 10); 31251.1Skamil 31261.54Skamil return (a + b * c - d) + (e * f - g / h); 31271.1Skamil} 31281.1Skamil 31291.54Skamilstatic void 31301.55Schristosbytes_transfer(int operation, size_t size, enum bytes_transfer_type type) 31311.1Skamil{ 31321.1Skamil const int exitval = 5; 31331.1Skamil const int sigval = SIGSTOP; 31341.1Skamil pid_t child, wpid; 31351.54Skamil bool skip = false; 31361.1Skamil 31371.54Skamil int lookup_me = 0; 31381.54Skamil uint8_t lookup_me8 = 0; 31391.54Skamil uint16_t lookup_me16 = 0; 31401.54Skamil uint32_t lookup_me32 = 0; 31411.54Skamil uint64_t lookup_me64 = 0; 31421.1Skamil 31431.54Skamil int magic = 0x13579246; 31441.54Skamil uint8_t magic8 = 0xab; 31451.54Skamil uint16_t magic16 = 0x1234; 31461.54Skamil uint32_t magic32 = 0x98765432; 31471.54Skamil uint64_t magic64 = 0xabcdef0123456789; 31481.1Skamil 31491.54Skamil struct ptrace_io_desc io; 31501.1Skamil#if defined(TWAIT_HAVE_STATUS) 31511.1Skamil int status; 31521.1Skamil#endif 31531.60Skre /* 513 is just enough, for the purposes of ATF it's good enough */ 31541.60Skre AuxInfo ai[513], *aip; 31551.55Schristos 31561.55Schristos ATF_REQUIRE(size < sizeof(ai)); 31571.1Skamil 31581.54Skamil /* Prepare variables for .TEXT transfers */ 31591.54Skamil switch (type) { 31601.54Skamil case BYTES_TRANSFER_TEXT: 31611.54Skamil memcpy(&magic, bytes_transfer_dummy, sizeof(magic)); 31621.54Skamil break; 31631.54Skamil case BYTES_TRANSFER_TEXTIO: 31641.54Skamil switch (size) { 31651.54Skamil case 8: 31661.54Skamil memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8)); 31671.54Skamil break; 31681.54Skamil case 16: 31691.54Skamil memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16)); 31701.54Skamil break; 31711.54Skamil case 32: 31721.54Skamil memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32)); 31731.54Skamil break; 31741.54Skamil case 64: 31751.54Skamil memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64)); 31761.54Skamil break; 31771.54Skamil } 31781.54Skamil break; 31791.54Skamil default: 31801.54Skamil break; 31811.54Skamil } 31821.1Skamil 31831.54Skamil /* Prepare variables for PIOD and AUXV transfers */ 31841.54Skamil switch (type) { 31851.54Skamil case BYTES_TRANSFER_TEXTIO: 31861.54Skamil case BYTES_TRANSFER_DATAIO: 31871.54Skamil io.piod_op = operation; 31881.54Skamil switch (size) { 31891.54Skamil case 8: 31901.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 31911.54Skamil (void *)bytes_transfer_dummy : 31921.54Skamil &lookup_me8; 31931.54Skamil io.piod_addr = &lookup_me8; 31941.54Skamil io.piod_len = sizeof(lookup_me8); 31951.54Skamil break; 31961.54Skamil case 16: 31971.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 31981.54Skamil (void *)bytes_transfer_dummy : 31991.54Skamil &lookup_me16; 32001.54Skamil io.piod_addr = &lookup_me16; 32011.54Skamil io.piod_len = sizeof(lookup_me16); 32021.54Skamil break; 32031.54Skamil case 32: 32041.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 32051.54Skamil (void *)bytes_transfer_dummy : 32061.54Skamil &lookup_me32; 32071.54Skamil io.piod_addr = &lookup_me32; 32081.54Skamil io.piod_len = sizeof(lookup_me32); 32091.54Skamil break; 32101.54Skamil case 64: 32111.54Skamil io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ? 32121.54Skamil (void *)bytes_transfer_dummy : 32131.54Skamil &lookup_me64; 32141.54Skamil io.piod_addr = &lookup_me64; 32151.54Skamil io.piod_len = sizeof(lookup_me64); 32161.54Skamil break; 32171.54Skamil default: 32181.54Skamil break; 32191.54Skamil } 32201.54Skamil break; 32211.54Skamil case BYTES_TRANSFER_AUXV: 32221.54Skamil io.piod_op = operation; 32231.54Skamil io.piod_offs = 0; 32241.54Skamil io.piod_addr = ai; 32251.54Skamil io.piod_len = size; 32261.54Skamil break; 32271.54Skamil default: 32281.54Skamil break; 32291.1Skamil } 32301.1Skamil 32311.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 32321.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 32331.1Skamil if (child == 0) { 32341.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 32351.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 32361.1Skamil 32371.54Skamil switch (type) { 32381.54Skamil case BYTES_TRANSFER_DATA: 32391.54Skamil switch (operation) { 32401.54Skamil case PT_READ_D: 32411.54Skamil case PT_READ_I: 32421.54Skamil lookup_me = magic; 32431.54Skamil break; 32441.54Skamil default: 32451.54Skamil break; 32461.54Skamil } 32471.54Skamil break; 32481.54Skamil case BYTES_TRANSFER_DATAIO: 32491.54Skamil switch (operation) { 32501.54Skamil case PIOD_READ_D: 32511.54Skamil case PIOD_READ_I: 32521.54Skamil switch (size) { 32531.54Skamil case 8: 32541.54Skamil lookup_me8 = magic8; 32551.54Skamil break; 32561.54Skamil case 16: 32571.54Skamil lookup_me16 = magic16; 32581.54Skamil break; 32591.54Skamil case 32: 32601.54Skamil lookup_me32 = magic32; 32611.54Skamil break; 32621.54Skamil case 64: 32631.54Skamil lookup_me64 = magic64; 32641.54Skamil break; 32651.54Skamil default: 32661.54Skamil break; 32671.54Skamil } 32681.54Skamil break; 32691.54Skamil default: 32701.54Skamil break; 32711.54Skamil } 32721.54Skamil default: 32731.54Skamil break; 32741.54Skamil } 32751.54Skamil 32761.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 32771.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 32781.1Skamil 32791.54Skamil /* Handle PIOD and PT separately as operation values overlap */ 32801.54Skamil switch (type) { 32811.54Skamil case BYTES_TRANSFER_DATA: 32821.54Skamil switch (operation) { 32831.54Skamil case PT_WRITE_D: 32841.54Skamil case PT_WRITE_I: 32851.54Skamil FORKEE_ASSERT_EQ(lookup_me, magic); 32861.54Skamil break; 32871.54Skamil default: 32881.54Skamil break; 32891.54Skamil } 32901.54Skamil break; 32911.54Skamil case BYTES_TRANSFER_DATAIO: 32921.54Skamil switch (operation) { 32931.54Skamil case PIOD_WRITE_D: 32941.54Skamil case PIOD_WRITE_I: 32951.54Skamil switch (size) { 32961.54Skamil case 8: 32971.54Skamil FORKEE_ASSERT_EQ(lookup_me8, magic8); 32981.54Skamil break; 32991.54Skamil case 16: 33001.54Skamil FORKEE_ASSERT_EQ(lookup_me16, magic16); 33011.54Skamil break; 33021.54Skamil case 32: 33031.54Skamil FORKEE_ASSERT_EQ(lookup_me32, magic32); 33041.54Skamil break; 33051.54Skamil case 64: 33061.54Skamil FORKEE_ASSERT_EQ(lookup_me64, magic64); 33071.54Skamil break; 33081.54Skamil default: 33091.54Skamil break; 33101.54Skamil } 33111.54Skamil break; 33121.54Skamil default: 33131.54Skamil break; 33141.54Skamil } 33151.54Skamil break; 33161.54Skamil case BYTES_TRANSFER_TEXT: 33171.54Skamil FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy, 33181.54Skamil sizeof(magic)) == 0); 33191.54Skamil break; 33201.54Skamil case BYTES_TRANSFER_TEXTIO: 33211.54Skamil switch (size) { 33221.54Skamil case 8: 33231.54Skamil FORKEE_ASSERT(memcmp(&magic8, 33241.54Skamil bytes_transfer_dummy, 33251.54Skamil sizeof(magic8)) == 0); 33261.54Skamil break; 33271.54Skamil case 16: 33281.54Skamil FORKEE_ASSERT(memcmp(&magic16, 33291.54Skamil bytes_transfer_dummy, 33301.54Skamil sizeof(magic16)) == 0); 33311.54Skamil break; 33321.54Skamil case 32: 33331.54Skamil FORKEE_ASSERT(memcmp(&magic32, 33341.54Skamil bytes_transfer_dummy, 33351.54Skamil sizeof(magic32)) == 0); 33361.54Skamil break; 33371.54Skamil case 64: 33381.54Skamil FORKEE_ASSERT(memcmp(&magic64, 33391.54Skamil bytes_transfer_dummy, 33401.54Skamil sizeof(magic64)) == 0); 33411.54Skamil break; 33421.54Skamil } 33431.54Skamil break; 33441.54Skamil default: 33451.54Skamil break; 33461.54Skamil } 33471.54Skamil 33481.13Schristos DPRINTF("Before exiting of the child process\n"); 33491.1Skamil _exit(exitval); 33501.1Skamil } 33511.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 33521.1Skamil 33531.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 33541.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33551.1Skamil 33561.1Skamil validate_status_stopped(status, sigval); 33571.1Skamil 33581.54Skamil /* Check PaX MPROTECT */ 33591.54Skamil if (!can_we_write_to_text(child)) { 33601.54Skamil switch (type) { 33611.54Skamil case BYTES_TRANSFER_TEXTIO: 33621.54Skamil switch (operation) { 33631.54Skamil case PIOD_WRITE_D: 33641.54Skamil case PIOD_WRITE_I: 33651.54Skamil skip = true; 33661.54Skamil break; 33671.54Skamil default: 33681.54Skamil break; 33691.54Skamil } 33701.54Skamil break; 33711.54Skamil case BYTES_TRANSFER_TEXT: 33721.54Skamil switch (operation) { 33731.54Skamil case PT_WRITE_D: 33741.54Skamil case PT_WRITE_I: 33751.54Skamil skip = true; 33761.54Skamil break; 33771.54Skamil default: 33781.54Skamil break; 33791.54Skamil } 33801.54Skamil break; 33811.54Skamil default: 33821.54Skamil break; 33831.54Skamil } 33841.54Skamil } 33851.1Skamil 33861.54Skamil /* Bailout cleanly killing the child process */ 33871.54Skamil if (skip) { 33881.54Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1); 33891.54Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 33901.54Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 33911.54Skamil child); 33921.1Skamil 33931.54Skamil validate_status_signaled(status, SIGKILL, 0); 33941.1Skamil 33951.54Skamil atf_tc_skip("PaX MPROTECT setup prevents writes to .text"); 33961.54Skamil } 33971.1Skamil 33981.54Skamil DPRINTF("Calling operation to transfer bytes between child=%d and " 33991.54Skamil "parent=%d\n", child, getpid()); 34001.1Skamil 34011.54Skamil switch (type) { 34021.54Skamil case BYTES_TRANSFER_TEXTIO: 34031.54Skamil case BYTES_TRANSFER_DATAIO: 34041.54Skamil case BYTES_TRANSFER_AUXV: 34051.54Skamil switch (operation) { 34061.54Skamil case PIOD_WRITE_D: 34071.54Skamil case PIOD_WRITE_I: 34081.54Skamil switch (size) { 34091.54Skamil case 8: 34101.54Skamil lookup_me8 = magic8; 34111.54Skamil break; 34121.54Skamil case 16: 34131.54Skamil lookup_me16 = magic16; 34141.54Skamil break; 34151.54Skamil case 32: 34161.54Skamil lookup_me32 = magic32; 34171.54Skamil break; 34181.54Skamil case 64: 34191.54Skamil lookup_me64 = magic64; 34201.54Skamil break; 34211.54Skamil default: 34221.54Skamil break; 34231.54Skamil } 34241.54Skamil break; 34251.54Skamil default: 34261.54Skamil break; 34271.54Skamil } 34281.54Skamil SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1); 34291.54Skamil switch (operation) { 34301.54Skamil case PIOD_READ_D: 34311.54Skamil case PIOD_READ_I: 34321.54Skamil switch (size) { 34331.54Skamil case 8: 34341.54Skamil ATF_REQUIRE_EQ(lookup_me8, magic8); 34351.54Skamil break; 34361.54Skamil case 16: 34371.54Skamil ATF_REQUIRE_EQ(lookup_me16, magic16); 34381.54Skamil break; 34391.54Skamil case 32: 34401.54Skamil ATF_REQUIRE_EQ(lookup_me32, magic32); 34411.54Skamil break; 34421.54Skamil case 64: 34431.54Skamil ATF_REQUIRE_EQ(lookup_me64, magic64); 34441.54Skamil break; 34451.54Skamil default: 34461.54Skamil break; 34471.54Skamil } 34481.54Skamil break; 34491.54Skamil case PIOD_READ_AUXV: 34501.54Skamil DPRINTF("Asserting that AUXV length (%zu) is > 0\n", 34511.54Skamil io.piod_len); 34521.54Skamil ATF_REQUIRE(io.piod_len > 0); 34531.54Skamil for (aip = ai; aip->a_type != AT_NULL; aip++) 34541.54Skamil DPRINTF("a_type=%#llx a_v=%#llx\n", 34551.54Skamil (long long int)aip->a_type, 34561.54Skamil (long long int)aip->a_v); 34571.54Skamil break; 34581.54Skamil default: 34591.54Skamil break; 34601.54Skamil } 34611.54Skamil break; 34621.54Skamil case BYTES_TRANSFER_TEXT: 34631.54Skamil switch (operation) { 34641.54Skamil case PT_READ_D: 34651.54Skamil case PT_READ_I: 34661.54Skamil errno = 0; 34671.54Skamil lookup_me = ptrace(operation, child, 34681.54Skamil bytes_transfer_dummy, 0); 34691.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 34701.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 34711.54Skamil break; 34721.54Skamil case PT_WRITE_D: 34731.54Skamil case PT_WRITE_I: 34741.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, 34751.54Skamil bytes_transfer_dummy, magic) 34761.54Skamil != -1); 34771.54Skamil break; 34781.54Skamil default: 34791.54Skamil break; 34801.54Skamil } 34811.54Skamil break; 34821.54Skamil case BYTES_TRANSFER_DATA: 34831.54Skamil switch (operation) { 34841.54Skamil case PT_READ_D: 34851.54Skamil case PT_READ_I: 34861.54Skamil errno = 0; 34871.54Skamil lookup_me = ptrace(operation, child, &lookup_me, 0); 34881.54Skamil ATF_REQUIRE_EQ(lookup_me, magic); 34891.54Skamil SYSCALL_REQUIRE_ERRNO(errno, 0); 34901.54Skamil break; 34911.54Skamil case PT_WRITE_D: 34921.54Skamil case PT_WRITE_I: 34931.54Skamil lookup_me = magic; 34941.54Skamil SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me, 34951.54Skamil magic) != -1); 34961.54Skamil break; 34971.54Skamil default: 34981.54Skamil break; 34991.54Skamil } 35001.54Skamil break; 35011.54Skamil default: 35021.54Skamil break; 35031.54Skamil } 35041.1Skamil 35051.13Schristos DPRINTF("Before resuming the child process where it left off and " 35061.1Skamil "without signal to be sent\n"); 35071.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 35081.1Skamil 35091.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 35101.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 35111.1Skamil 35121.1Skamil validate_status_exited(status, exitval); 35131.1Skamil 35141.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 35151.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 35161.1Skamil} 35171.1Skamil 35181.61Skre#define BYTES_TRANSFER(test, operation, size, type) \ 35191.61SkreATF_TC(test); \ 35201.61SkreATF_TC_HEAD(test, tc) \ 35211.61Skre{ \ 35221.61Skre atf_tc_set_md_var(tc, "descr", \ 35231.61Skre "Verify bytes transfer operation" #operation " and size " #size \ 35241.61Skre " of type " #type); \ 35251.61Skre} \ 35261.61Skre \ 35271.61SkreATF_TC_BODY(test, tc) \ 35281.61Skre{ \ 35291.61Skre \ 35301.61Skre bytes_transfer(operation, size, BYTES_TRANSFER_##type); \ 35311.1Skamil} 35321.1Skamil 35331.54Skamil// DATA 35341.1Skamil 35351.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO) 35361.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO) 35371.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO) 35381.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO) 35391.54Skamil 35401.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO) 35411.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO) 35421.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO) 35431.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO) 35441.54Skamil 35451.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO) 35461.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO) 35471.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO) 35481.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO) 35491.54Skamil 35501.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO) 35511.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO) 35521.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO) 35531.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO) 35541.54Skamil 35551.54SkamilBYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA) 35561.54SkamilBYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA) 35571.54SkamilBYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA) 35581.54SkamilBYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA) 35591.54Skamil 35601.54Skamil// TEXT 35611.54Skamil 35621.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO) 35631.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO) 35641.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO) 35651.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO) 35661.54Skamil 35671.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO) 35681.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO) 35691.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO) 35701.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO) 35711.54Skamil 35721.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO) 35731.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO) 35741.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO) 35751.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO) 35761.54Skamil 35771.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO) 35781.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO) 35791.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO) 35801.54SkamilBYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO) 35811.54Skamil 35821.54SkamilBYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT) 35831.54SkamilBYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT) 35841.54SkamilBYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT) 35851.54SkamilBYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT) 35861.1Skamil 35871.54Skamil// AUXV 35881.1Skamil 35891.54SkamilBYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV) 35901.1Skamil 35911.54Skamil/// ---------------------------------------------------------------------------- 35921.1Skamil 35931.76Sscole#if defined(HAVE_GPREGS) || defined(HAVE_FPREGS) 35941.72Skamilstatic void 35951.72Skamilaccess_regs(const char *regset, const char *aux) 35961.1Skamil{ 35971.1Skamil const int exitval = 5; 35981.1Skamil const int sigval = SIGSTOP; 35991.1Skamil pid_t child, wpid; 36001.1Skamil#if defined(TWAIT_HAVE_STATUS) 36011.1Skamil int status; 36021.1Skamil#endif 36031.72Skamil#if defined(HAVE_GPREGS) 36041.72Skamil struct reg gpr; 36051.76Sscole register_t rgstr; 36061.1Skamil#endif 36071.72Skamil#if defined(HAVE_FPREGS) 36081.72Skamil struct fpreg fpr; 36091.1Skamil#endif 36101.76Sscole 36111.72Skamil#if !defined(HAVE_GPREGS) 36121.72Skamil if (strcmp(regset, "regs") == 0) 36131.72Skamil atf_tc_fail("Impossible test scenario!"); 36141.1Skamil#endif 36151.1Skamil 36161.72Skamil#if !defined(HAVE_FPREGS) 36171.72Skamil if (strcmp(regset, "fpregs") == 0) 36181.72Skamil atf_tc_fail("Impossible test scenario!"); 36191.1Skamil#endif 36201.1Skamil 36211.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 36221.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 36231.1Skamil if (child == 0) { 36241.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 36251.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 36261.1Skamil 36271.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 36281.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 36291.1Skamil 36301.13Schristos DPRINTF("Before exiting of the child process\n"); 36311.1Skamil _exit(exitval); 36321.1Skamil } 36331.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 36341.1Skamil 36351.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 36361.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 36371.1Skamil 36381.1Skamil validate_status_stopped(status, sigval); 36391.1Skamil 36401.1Skamil#if defined(HAVE_GPREGS) 36411.72Skamil if (strcmp(regset, "regs") == 0) { 36421.72Skamil DPRINTF("Call GETREGS for the child process\n"); 36431.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1); 36441.72Skamil 36451.72Skamil if (strcmp(aux, "none") == 0) { 36461.72Skamil DPRINTF("Retrieved registers\n"); 36471.72Skamil } else if (strcmp(aux, "pc") == 0) { 36481.72Skamil rgstr = PTRACE_REG_PC(&gpr); 36491.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 36501.72Skamil } else if (strcmp(aux, "set_pc") == 0) { 36511.72Skamil rgstr = PTRACE_REG_PC(&gpr); 36521.72Skamil PTRACE_REG_SET_PC(&gpr, rgstr); 36531.72Skamil } else if (strcmp(aux, "sp") == 0) { 36541.72Skamil rgstr = PTRACE_REG_SP(&gpr); 36551.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 36561.72Skamil } else if (strcmp(aux, "intrv") == 0) { 36571.72Skamil rgstr = PTRACE_REG_INTRV(&gpr); 36581.72Skamil DPRINTF("Retrieved %" PRIxREGISTER "\n", rgstr); 36591.72Skamil } else if (strcmp(aux, "setregs") == 0) { 36601.72Skamil DPRINTF("Call SETREGS for the child process\n"); 36611.72Skamil SYSCALL_REQUIRE( 36621.72Skamil ptrace(PT_GETREGS, child, &gpr, 0) != -1); 36631.72Skamil } 36641.72Skamil } 36651.1Skamil#endif 36661.1Skamil 36671.72Skamil#if defined(HAVE_FPREGS) 36681.72Skamil if (strcmp(regset, "fpregs") == 0) { 36691.72Skamil DPRINTF("Call GETFPREGS for the child process\n"); 36701.72Skamil SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1); 36711.72Skamil 36721.72Skamil if (strcmp(aux, "getfpregs") == 0) { 36731.72Skamil DPRINTF("Retrieved FP registers\n"); 36741.72Skamil } else if (strcmp(aux, "setfpregs") == 0) { 36751.72Skamil DPRINTF("Call SETFPREGS for the child\n"); 36761.72Skamil SYSCALL_REQUIRE( 36771.72Skamil ptrace(PT_SETFPREGS, child, &fpr, 0) != -1); 36781.72Skamil } 36791.1Skamil } 36801.1Skamil#endif 36811.1Skamil 36821.13Schristos DPRINTF("Before resuming the child process where it left off and " 36831.1Skamil "without signal to be sent\n"); 36841.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 36851.1Skamil 36861.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 36871.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 36881.1Skamil 36891.1Skamil validate_status_exited(status, exitval); 36901.1Skamil 36911.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 36921.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 36931.1Skamil} 36941.1Skamil 36951.72Skamil#define ACCESS_REGS(test, regset, aux) \ 36961.72SkamilATF_TC(test); \ 36971.72SkamilATF_TC_HEAD(test, tc) \ 36981.72Skamil{ \ 36991.72Skamil atf_tc_set_md_var(tc, "descr", \ 37001.72Skamil "Verify " regset " with auxiliary operation: " aux); \ 37011.72Skamil} \ 37021.72Skamil \ 37031.72SkamilATF_TC_BODY(test, tc) \ 37041.72Skamil{ \ 37051.72Skamil \ 37061.72Skamil access_regs(regset, aux); \ 37071.1Skamil} 37081.1Skamil#endif 37091.1Skamil 37101.72Skamil#if defined(HAVE_GPREGS) 37111.72SkamilACCESS_REGS(access_regs1, "regs", "none") 37121.72SkamilACCESS_REGS(access_regs2, "regs", "pc") 37131.72SkamilACCESS_REGS(access_regs3, "regs", "set_pc") 37141.72SkamilACCESS_REGS(access_regs4, "regs", "sp") 37151.72SkamilACCESS_REGS(access_regs5, "regs", "intrv") 37161.72SkamilACCESS_REGS(access_regs6, "regs", "setregs") 37171.1Skamil#endif 37181.1Skamil#if defined(HAVE_FPREGS) 37191.72SkamilACCESS_REGS(access_fpregs1, "fpregs", "getfpregs") 37201.72SkamilACCESS_REGS(access_fpregs2, "fpregs", "setfpregs") 37211.1Skamil#endif 37221.1Skamil 37231.72Skamil/// ---------------------------------------------------------------------------- 37241.1Skamil 37251.1Skamil#if defined(PT_STEP) 37261.1Skamilstatic void 37271.95Skamilptrace_step(int N, int setstep, bool masked, bool ignored) 37281.1Skamil{ 37291.1Skamil const int exitval = 5; 37301.1Skamil const int sigval = SIGSTOP; 37311.1Skamil pid_t child, wpid; 37321.1Skamil#if defined(TWAIT_HAVE_STATUS) 37331.1Skamil int status; 37341.1Skamil#endif 37351.1Skamil int happy; 37361.95Skamil struct sigaction sa; 37371.81Skamil struct ptrace_siginfo info; 37381.95Skamil sigset_t intmask; 37391.95Skamil struct kinfo_proc2 kp; 37401.95Skamil size_t len = sizeof(kp); 37411.95Skamil 37421.95Skamil int name[6]; 37431.95Skamil const size_t namelen = __arraycount(name); 37441.95Skamil ki_sigset_t kp_sigmask; 37451.95Skamil ki_sigset_t kp_sigignore; 37461.1Skamil 37471.1Skamil#if defined(__arm__) 37481.1Skamil /* PT_STEP not supported on arm 32-bit */ 37491.1Skamil atf_tc_expect_fail("PR kern/52119"); 37501.1Skamil#endif 37511.1Skamil 37521.95Skamil if (masked || ignored) 37531.95Skamil atf_tc_expect_fail("Unexpected sigmask reset on crash under " 37541.95Skamil "debugger"); 37551.95Skamil 37561.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 37571.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 37581.1Skamil if (child == 0) { 37591.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 37601.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 37611.1Skamil 37621.95Skamil if (masked) { 37631.95Skamil sigemptyset(&intmask); 37641.95Skamil sigaddset(&intmask, SIGTRAP); 37651.95Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 37661.95Skamil } 37671.95Skamil 37681.95Skamil if (ignored) { 37691.95Skamil memset(&sa, 0, sizeof(sa)); 37701.95Skamil sa.sa_handler = SIG_IGN; 37711.95Skamil sigemptyset(&sa.sa_mask); 37721.95Skamil FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1); 37731.95Skamil } 37741.95Skamil 37751.1Skamil happy = check_happy(999); 37761.1Skamil 37771.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 37781.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 37791.1Skamil 37801.1Skamil FORKEE_ASSERT_EQ(happy, check_happy(999)); 37811.1Skamil 37821.13Schristos DPRINTF("Before exiting of the child process\n"); 37831.1Skamil _exit(exitval); 37841.1Skamil } 37851.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 37861.1Skamil 37871.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 37881.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 37891.1Skamil 37901.1Skamil validate_status_stopped(status, sigval); 37911.1Skamil 37921.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 37931.81Skamil SYSCALL_REQUIRE( 37941.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 37951.81Skamil 37961.81Skamil DPRINTF("Before checking siginfo_t\n"); 37971.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 37981.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 37991.81Skamil 38001.95Skamil name[0] = CTL_KERN, 38011.95Skamil name[1] = KERN_PROC2, 38021.95Skamil name[2] = KERN_PROC_PID; 38031.95Skamil name[3] = child; 38041.95Skamil name[4] = sizeof(kp); 38051.95Skamil name[5] = 1; 38061.95Skamil 38071.95Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 38081.95Skamil 38091.95Skamil if (masked) 38101.95Skamil kp_sigmask = kp.p_sigmask; 38111.95Skamil 38121.95Skamil if (ignored) 38131.95Skamil kp_sigignore = kp.p_sigignore; 38141.95Skamil 38151.1Skamil while (N --> 0) { 38161.2Skamil if (setstep) { 38171.13Schristos DPRINTF("Before resuming the child process where it " 38181.2Skamil "left off and without signal to be sent (use " 38191.9Skamil "PT_SETSTEP and PT_CONTINUE)\n"); 38201.13Schristos SYSCALL_REQUIRE(ptrace(PT_SETSTEP, child, 0, 0) != -1); 38211.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) 38221.2Skamil != -1); 38231.2Skamil } else { 38241.13Schristos DPRINTF("Before resuming the child process where it " 38251.2Skamil "left off and without signal to be sent (use " 38261.2Skamil "PT_STEP)\n"); 38271.13Schristos SYSCALL_REQUIRE(ptrace(PT_STEP, child, (void *)1, 0) 38281.2Skamil != -1); 38291.2Skamil } 38301.1Skamil 38311.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38321.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 38331.1Skamil child); 38341.1Skamil 38351.1Skamil validate_status_stopped(status, SIGTRAP); 38361.2Skamil 38371.81Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 38381.81Skamil SYSCALL_REQUIRE( 38391.81Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 38401.81Skamil 38411.81Skamil DPRINTF("Before checking siginfo_t\n"); 38421.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 38431.81Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_TRACE); 38441.81Skamil 38451.2Skamil if (setstep) { 38461.13Schristos SYSCALL_REQUIRE(ptrace(PT_CLEARSTEP, child, 0, 0) != -1); 38471.2Skamil } 38481.95Skamil 38491.95Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 38501.95Skamil 38511.95Skamil if (masked) { 38521.95Skamil DPRINTF("kp_sigmask=" 38531.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 38541.95Skamil PRIx32 "\n", 38551.95Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 38561.95Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 38571.95Skamil 38581.95Skamil DPRINTF("kp.p_sigmask=" 38591.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 38601.95Skamil PRIx32 "\n", 38611.95Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 38621.95Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 38631.95Skamil 38641.95Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 38651.95Skamil sizeof(kp_sigmask))); 38661.95Skamil } 38671.95Skamil 38681.95Skamil if (ignored) { 38691.95Skamil DPRINTF("kp_sigignore=" 38701.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 38711.95Skamil PRIx32 "\n", 38721.95Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 38731.95Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 38741.95Skamil 38751.95Skamil DPRINTF("kp.p_sigignore=" 38761.95Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 38771.95Skamil PRIx32 "\n", 38781.95Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 38791.95Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 38801.95Skamil 38811.95Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 38821.95Skamil sizeof(kp_sigignore))); 38831.95Skamil } 38841.1Skamil } 38851.1Skamil 38861.13Schristos DPRINTF("Before resuming the child process where it left off and " 38871.1Skamil "without signal to be sent\n"); 38881.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 38891.1Skamil 38901.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38911.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 38921.1Skamil 38931.1Skamil validate_status_exited(status, exitval); 38941.1Skamil 38951.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38961.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 38971.1Skamil} 38981.1Skamil 38991.73Skamil#define PTRACE_STEP(test, N, setstep) \ 39001.73SkamilATF_TC(test); \ 39011.73SkamilATF_TC_HEAD(test, tc) \ 39021.73Skamil{ \ 39031.73Skamil atf_tc_set_md_var(tc, "descr", \ 39041.74Skamil "Verify " #N " (PT_SETSTEP set to: " #setstep ")"); \ 39051.73Skamil} \ 39061.73Skamil \ 39071.73SkamilATF_TC_BODY(test, tc) \ 39081.73Skamil{ \ 39091.73Skamil \ 39101.95Skamil ptrace_step(N, setstep, false, false); \ 39111.1Skamil} 39121.1Skamil 39131.73SkamilPTRACE_STEP(step1, 1, 0) 39141.73SkamilPTRACE_STEP(step2, 2, 0) 39151.73SkamilPTRACE_STEP(step3, 3, 0) 39161.73SkamilPTRACE_STEP(step4, 4, 0) 39171.73SkamilPTRACE_STEP(setstep1, 1, 1) 39181.73SkamilPTRACE_STEP(setstep2, 2, 1) 39191.73SkamilPTRACE_STEP(setstep3, 3, 1) 39201.73SkamilPTRACE_STEP(setstep4, 4, 1) 39211.95Skamil 39221.95SkamilATF_TC(step_signalmasked); 39231.95SkamilATF_TC_HEAD(step_signalmasked, tc) 39241.95Skamil{ 39251.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with masked SIGTRAP"); 39261.95Skamil} 39271.95Skamil 39281.95SkamilATF_TC_BODY(step_signalmasked, tc) 39291.95Skamil{ 39301.95Skamil 39311.95Skamil ptrace_step(1, 0, true, false); 39321.95Skamil} 39331.95Skamil 39341.95SkamilATF_TC(step_signalignored); 39351.95SkamilATF_TC_HEAD(step_signalignored, tc) 39361.95Skamil{ 39371.95Skamil atf_tc_set_md_var(tc, "descr", "Verify PT_STEP with ignored SIGTRAP"); 39381.95Skamil} 39391.95Skamil 39401.95SkamilATF_TC_BODY(step_signalignored, tc) 39411.95Skamil{ 39421.95Skamil 39431.95Skamil ptrace_step(1, 0, false, true); 39441.95Skamil} 39451.1Skamil#endif 39461.1Skamil 39471.73Skamil/// ---------------------------------------------------------------------------- 39481.1Skamil 39491.75Skamilstatic void 39501.75Skamilptrace_kill(const char *type) 39511.1Skamil{ 39521.75Skamil const int sigval = SIGSTOP; 39531.1Skamil pid_t child, wpid; 39541.1Skamil#if defined(TWAIT_HAVE_STATUS) 39551.1Skamil int status; 39561.1Skamil#endif 39571.1Skamil 39581.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 39591.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 39601.1Skamil if (child == 0) { 39611.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 39621.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 39631.1Skamil 39641.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 39651.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 39661.1Skamil 39671.1Skamil /* NOTREACHED */ 39681.1Skamil FORKEE_ASSERTX(0 && 39691.1Skamil "Child should be terminated by a signal from its parent"); 39701.1Skamil } 39711.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 39721.1Skamil 39731.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39741.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 39751.1Skamil 39761.1Skamil validate_status_stopped(status, sigval); 39771.1Skamil 39781.75Skamil DPRINTF("Before killing the child process with %s\n", type); 39791.75Skamil if (strcmp(type, "ptrace(PT_KILL)") == 0) { 39801.75Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void*)1, 0) != -1); 39811.75Skamil } else if (strcmp(type, "kill(SIGKILL)") == 0) { 39821.75Skamil kill(child, SIGKILL); 39831.75Skamil } else if (strcmp(type, "killpg(SIGKILL)") == 0) { 39841.75Skamil setpgid(child, 0); 39851.75Skamil killpg(getpgid(child), SIGKILL); 39861.75Skamil } 39871.1Skamil 39881.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39891.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 39901.1Skamil 39911.75Skamil validate_status_signaled(status, SIGKILL, 0); 39921.1Skamil 39931.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39941.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 39951.1Skamil} 39961.1Skamil 39971.75Skamil#define PTRACE_KILL(test, type) \ 39981.75SkamilATF_TC(test); \ 39991.75SkamilATF_TC_HEAD(test, tc) \ 40001.75Skamil{ \ 40011.75Skamil atf_tc_set_md_var(tc, "descr", \ 40021.75Skamil "Verify killing the child with " type); \ 40031.75Skamil} \ 40041.75Skamil \ 40051.75SkamilATF_TC_BODY(test, tc) \ 40061.75Skamil{ \ 40071.75Skamil \ 40081.75Skamil ptrace_kill(type); \ 40091.1Skamil} 40101.1Skamil 40111.75Skamil// PT_CONTINUE with SIGKILL is covered by traceme_sendsignal_simple1 40121.75SkamilPTRACE_KILL(kill1, "ptrace(PT_KILL)") 40131.75SkamilPTRACE_KILL(kill2, "kill(SIGKILL)") 40141.75SkamilPTRACE_KILL(kill3, "killpg(SIGKILL)") 40151.1Skamil 40161.75Skamil/// ---------------------------------------------------------------------------- 40171.1Skamil 40181.77Skamilstatic void 40191.77Skamiltraceme_lwpinfo(const int threads) 40201.1Skamil{ 40211.1Skamil const int sigval = SIGSTOP; 40221.77Skamil const int sigval2 = SIGINT; 40231.1Skamil pid_t child, wpid; 40241.1Skamil#if defined(TWAIT_HAVE_STATUS) 40251.1Skamil int status; 40261.1Skamil#endif 40271.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 40281.77Skamil struct ptrace_siginfo info; 40291.77Skamil 40301.77Skamil /* Maximum number of supported threads in this test */ 40311.77Skamil pthread_t t[3]; 40321.77Skamil int n, rv; 40331.77Skamil 40341.77Skamil ATF_REQUIRE((int)__arraycount(t) >= threads); 40351.1Skamil 40361.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 40371.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 40381.1Skamil if (child == 0) { 40391.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 40401.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 40411.1Skamil 40421.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 40431.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 40441.1Skamil 40451.77Skamil for (n = 0; n < threads; n++) { 40461.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 40471.77Skamil FORKEE_ASSERT(rv == 0); 40481.77Skamil } 40491.77Skamil 40501.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval2)); 40511.77Skamil FORKEE_ASSERT(raise(sigval2) == 0); 40521.77Skamil 40531.77Skamil /* NOTREACHED */ 40541.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 40551.1Skamil } 40561.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 40571.1Skamil 40581.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 40591.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 40601.1Skamil 40611.1Skamil validate_status_stopped(status, sigval); 40621.1Skamil 40631.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 40641.77Skamil SYSCALL_REQUIRE( 40651.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 40661.77Skamil 40671.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 40681.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 40691.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 40701.77Skamil info.psi_siginfo.si_errno); 40711.77Skamil 40721.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 40731.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 40741.77Skamil 40751.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 40761.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 40771.1Skamil 40781.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 40791.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 40801.1Skamil 40811.13Schristos DPRINTF("Assert that lwp thread %d received event PL_EVENT_SIGNAL\n", 40821.77Skamil lwp.pl_lwpid); 40831.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 40841.1Skamil 40851.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 40861.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 40871.1Skamil 40881.77Skamil DPRINTF("Assert that there exists a single thread only\n"); 40891.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 40901.1Skamil 40911.13Schristos DPRINTF("Before resuming the child process where it left off and " 40921.1Skamil "without signal to be sent\n"); 40931.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 40941.1Skamil 40951.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 40961.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 40971.1Skamil 40981.77Skamil validate_status_stopped(status, sigval2); 40991.77Skamil 41001.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 41011.77Skamil SYSCALL_REQUIRE( 41021.77Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 41031.77Skamil 41041.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 41051.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 41061.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 41071.77Skamil info.psi_siginfo.si_errno); 41081.77Skamil 41091.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2); 41101.77Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 41111.77Skamil 41121.77Skamil memset(&lwp, 0, sizeof(lwp)); 41131.77Skamil 41141.77Skamil for (n = 0; n <= threads; n++) { 41151.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 41161.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 41171.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 41181.77Skamil 41191.77Skamil DPRINTF("Assert that the thread exists\n"); 41201.77Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 41211.77Skamil 41221.77Skamil DPRINTF("Assert that lwp thread %d received expected event\n", 41231.77Skamil lwp.pl_lwpid); 41241.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, info.psi_lwpid == lwp.pl_lwpid ? 41251.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 41261.77Skamil } 41271.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 41281.77Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 41291.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 41301.77Skamil 41311.77Skamil DPRINTF("Assert that there are no more threads\n"); 41321.77Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 41331.77Skamil 41341.77Skamil DPRINTF("Before resuming the child process where it left off and " 41351.77Skamil "without signal to be sent\n"); 41361.77Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1); 41371.77Skamil 41381.77Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41391.77Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 41401.77Skamil 41411.77Skamil validate_status_signaled(status, SIGKILL, 0); 41421.1Skamil 41431.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41441.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 41451.1Skamil} 41461.1Skamil 41471.77Skamil#define TRACEME_LWPINFO(test, threads) \ 41481.77SkamilATF_TC(test); \ 41491.77SkamilATF_TC_HEAD(test, tc) \ 41501.77Skamil{ \ 41511.77Skamil atf_tc_set_md_var(tc, "descr", \ 41521.77Skamil "Verify LWPINFO with the child with " #threads \ 41531.77Skamil " spawned extra threads"); \ 41541.77Skamil} \ 41551.77Skamil \ 41561.77SkamilATF_TC_BODY(test, tc) \ 41571.77Skamil{ \ 41581.77Skamil \ 41591.77Skamil traceme_lwpinfo(threads); \ 41601.1Skamil} 41611.1Skamil 41621.77SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0) 41631.77SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1) 41641.77SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2) 41651.77SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3) 41661.77Skamil 41671.77Skamil/// ---------------------------------------------------------------------------- 41681.77Skamil 41691.77Skamil#if defined(TWAIT_HAVE_PID) 41701.77Skamilstatic void 41711.77Skamilattach_lwpinfo(const int threads) 41721.1Skamil{ 41731.77Skamil const int sigval = SIGINT; 41741.1Skamil struct msg_fds parent_tracee, parent_tracer; 41751.1Skamil const int exitval_tracer = 10; 41761.1Skamil pid_t tracee, tracer, wpid; 41771.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 41781.1Skamil#if defined(TWAIT_HAVE_STATUS) 41791.1Skamil int status; 41801.1Skamil#endif 41811.77Skamil struct ptrace_lwpinfo lwp = {0, 0}; 41821.77Skamil struct ptrace_siginfo info; 41831.77Skamil 41841.77Skamil /* Maximum number of supported threads in this test */ 41851.77Skamil pthread_t t[3]; 41861.77Skamil int n, rv; 41871.1Skamil 41881.13Schristos DPRINTF("Spawn tracee\n"); 41891.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 41901.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 41911.1Skamil tracee = atf_utils_fork(); 41921.1Skamil if (tracee == 0) { 41931.1Skamil /* Wait for message from the parent */ 41941.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 41951.1Skamil 41961.77Skamil CHILD_FROM_PARENT("spawn threads", parent_tracee, msg); 41971.77Skamil 41981.77Skamil for (n = 0; n < threads; n++) { 41991.77Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 42001.77Skamil FORKEE_ASSERT(rv == 0); 42011.77Skamil } 42021.77Skamil 42031.77Skamil CHILD_TO_PARENT("tracee exit", parent_tracee, msg); 42041.77Skamil 42051.77Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 42061.77Skamil FORKEE_ASSERT(raise(sigval) == 0); 42071.77Skamil 42081.77Skamil /* NOTREACHED */ 42091.77Skamil FORKEE_ASSERTX(0 && "Not reached"); 42101.1Skamil } 42111.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 42121.1Skamil 42131.13Schristos DPRINTF("Spawn debugger\n"); 42141.1Skamil tracer = atf_utils_fork(); 42151.1Skamil if (tracer == 0) { 42161.1Skamil /* No IPC to communicate with the child */ 42171.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 42181.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 42191.1Skamil 42201.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 42211.1Skamil FORKEE_REQUIRE_SUCCESS( 42221.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 42231.1Skamil 42241.1Skamil forkee_status_stopped(status, SIGSTOP); 42251.1Skamil 42261.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 42271.77Skamil "tracee"); 42281.77Skamil FORKEE_ASSERT( 42291.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 42301.77Skamil 42311.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 42321.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 42331.77Skamil "si_errno=%#x\n", 42341.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 42351.77Skamil info.psi_siginfo.si_errno); 42361.77Skamil 42371.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 42381.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 42391.77Skamil 42401.13Schristos DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 42411.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 42421.1Skamil != -1); 42431.1Skamil 42441.13Schristos DPRINTF("Assert that there exists a thread\n"); 42451.77Skamil FORKEE_ASSERTX(lwp.pl_lwpid > 0); 42461.1Skamil 42471.13Schristos DPRINTF("Assert that lwp thread %d received event " 42481.77Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 42491.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 42501.1Skamil 42511.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 42521.77Skamil "tracee\n"); 42531.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 42541.1Skamil != -1); 42551.1Skamil 42561.77Skamil DPRINTF("Assert that there are no more lwp threads in " 42571.77Skamil "tracee\n"); 42581.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 42591.1Skamil 42601.1Skamil /* Resume tracee with PT_CONTINUE */ 42611.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 42621.1Skamil 42631.1Skamil /* Inform parent that tracer has attached to tracee */ 42641.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 42651.77Skamil 42661.1Skamil /* Wait for parent */ 42671.1Skamil CHILD_FROM_PARENT("tracer wait", parent_tracer, msg); 42681.1Skamil 42691.77Skamil /* Wait for tracee and assert that it raised a signal */ 42701.77Skamil FORKEE_REQUIRE_SUCCESS( 42711.77Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 42721.77Skamil 42731.77Skamil forkee_status_stopped(status, SIGINT); 42741.77Skamil 42751.77Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 42761.77Skamil "child"); 42771.77Skamil FORKEE_ASSERT( 42781.77Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 42791.77Skamil 42801.77Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 42811.77Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 42821.77Skamil "si_errno=%#x\n", 42831.77Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 42841.77Skamil info.psi_siginfo.si_errno); 42851.77Skamil 42861.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 42871.77Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 42881.77Skamil 42891.77Skamil memset(&lwp, 0, sizeof(lwp)); 42901.77Skamil 42911.77Skamil for (n = 0; n <= threads; n++) { 42921.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 42931.77Skamil "child\n"); 42941.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, 42951.77Skamil sizeof(lwp)) != -1); 42961.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 42971.77Skamil 42981.77Skamil DPRINTF("Assert that the thread exists\n"); 42991.77Skamil FORKEE_ASSERT(lwp.pl_lwpid > 0); 43001.77Skamil 43011.77Skamil DPRINTF("Assert that lwp thread %d received expected " 43021.77Skamil "event\n", lwp.pl_lwpid); 43031.77Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 43041.77Skamil info.psi_lwpid == lwp.pl_lwpid ? 43051.77Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 43061.77Skamil } 43071.77Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 43081.77Skamil "tracee\n"); 43091.77Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 43101.77Skamil != -1); 43111.77Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 43121.77Skamil 43131.77Skamil DPRINTF("Assert that there are no more threads\n"); 43141.77Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 43151.77Skamil 43161.77Skamil DPRINTF("Before resuming the child process where it left off " 43171.77Skamil "and without signal to be sent\n"); 43181.77Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL) 43191.77Skamil != -1); 43201.77Skamil 43211.1Skamil /* Wait for tracee and assert that it exited */ 43221.1Skamil FORKEE_REQUIRE_SUCCESS( 43231.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 43241.1Skamil 43251.77Skamil forkee_status_signaled(status, SIGKILL, 0); 43261.1Skamil 43271.13Schristos DPRINTF("Before exiting of the tracer process\n"); 43281.1Skamil _exit(exitval_tracer); 43291.1Skamil } 43301.1Skamil 43311.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 43321.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 43331.1Skamil 43341.77Skamil DPRINTF("Resume the tracee and spawn threads\n"); 43351.77Skamil PARENT_TO_CHILD("spawn threads", parent_tracee, msg); 43361.77Skamil 43371.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 43381.77Skamil PARENT_FROM_CHILD("tracee exit", parent_tracee, msg); 43391.1Skamil 43401.77Skamil DPRINTF("Resume the tracer and let it detect multiple threads\n"); 43411.1Skamil PARENT_TO_CHILD("tracer wait", parent_tracer, msg); 43421.1Skamil 43431.13Schristos DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n", 43441.1Skamil TWAIT_FNAME); 43451.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 43461.1Skamil tracer); 43471.1Skamil 43481.1Skamil validate_status_exited(status, exitval_tracer); 43491.1Skamil 43501.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 43511.1Skamil TWAIT_FNAME); 43521.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 43531.1Skamil tracee); 43541.1Skamil 43551.77Skamil validate_status_signaled(status, SIGKILL, 0); 43561.1Skamil 43571.1Skamil msg_close(&parent_tracer); 43581.1Skamil msg_close(&parent_tracee); 43591.1Skamil} 43601.77Skamil 43611.77Skamil#define ATTACH_LWPINFO(test, threads) \ 43621.77SkamilATF_TC(test); \ 43631.77SkamilATF_TC_HEAD(test, tc) \ 43641.77Skamil{ \ 43651.77Skamil atf_tc_set_md_var(tc, "descr", \ 43661.77Skamil "Verify LWPINFO with the child with " #threads \ 43671.77Skamil " spawned extra threads (tracer is not the original " \ 43681.77Skamil "parent)"); \ 43691.77Skamil} \ 43701.77Skamil \ 43711.77SkamilATF_TC_BODY(test, tc) \ 43721.77Skamil{ \ 43731.77Skamil \ 43741.77Skamil attach_lwpinfo(threads); \ 43751.77Skamil} 43761.77Skamil 43771.77SkamilATTACH_LWPINFO(attach_lwpinfo0, 0) 43781.77SkamilATTACH_LWPINFO(attach_lwpinfo1, 1) 43791.77SkamilATTACH_LWPINFO(attach_lwpinfo2, 2) 43801.77SkamilATTACH_LWPINFO(attach_lwpinfo3, 3) 43811.1Skamil#endif 43821.1Skamil 43831.77Skamil/// ---------------------------------------------------------------------------- 43841.77Skamil 43851.1Skamilstatic void 43861.79Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught) 43871.1Skamil{ 43881.1Skamil const int exitval = 5; 43891.1Skamil const int sigval = SIGINT; 43901.1Skamil const int sigfaked = SIGTRAP; 43911.1Skamil const int sicodefaked = TRAP_BRKPT; 43921.1Skamil pid_t child, wpid; 43931.1Skamil struct sigaction sa; 43941.1Skamil#if defined(TWAIT_HAVE_STATUS) 43951.1Skamil int status; 43961.1Skamil#endif 43971.1Skamil struct ptrace_siginfo info; 43981.1Skamil memset(&info, 0, sizeof(info)); 43991.1Skamil 44001.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 44011.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 44021.1Skamil if (child == 0) { 44031.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 44041.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 44051.1Skamil 44061.79Skamil sa.sa_sigaction = sah; 44071.1Skamil sa.sa_flags = SA_SIGINFO; 44081.1Skamil sigemptyset(&sa.sa_mask); 44091.1Skamil 44101.79Skamil FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL) 44111.79Skamil != -1); 44121.1Skamil 44131.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 44141.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 44151.1Skamil 44161.79Skamil FORKEE_ASSERT_EQ(*signal_caught, 1); 44171.1Skamil 44181.13Schristos DPRINTF("Before exiting of the child process\n"); 44191.1Skamil _exit(exitval); 44201.1Skamil } 44211.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 44221.1Skamil 44231.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44241.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44251.1Skamil 44261.1Skamil validate_status_stopped(status, sigval); 44271.1Skamil 44281.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 44291.61Skre SYSCALL_REQUIRE( 44301.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 44311.1Skamil 44321.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 44331.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 44341.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 44351.1Skamil info.psi_siginfo.si_errno); 44361.1Skamil 44371.79Skamil if (faked) { 44381.79Skamil DPRINTF("Before setting new faked signal to signo=%d " 44391.79Skamil "si_code=%d\n", sigfaked, sicodefaked); 44401.79Skamil info.psi_siginfo.si_signo = sigfaked; 44411.79Skamil info.psi_siginfo.si_code = sicodefaked; 44421.79Skamil } 44431.1Skamil 44441.13Schristos DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n"); 44451.61Skre SYSCALL_REQUIRE( 44461.61Skre ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1); 44471.1Skamil 44481.79Skamil if (faked) { 44491.79Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 44501.79Skamil "child\n"); 44511.79Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 44521.79Skamil sizeof(info)) != -1); 44531.1Skamil 44541.79Skamil DPRINTF("Before checking siginfo_t\n"); 44551.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked); 44561.79Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked); 44571.79Skamil } 44581.1Skamil 44591.13Schristos DPRINTF("Before resuming the child process where it left off and " 44601.1Skamil "without signal to be sent\n"); 44611.79Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 44621.79Skamil faked ? sigfaked : sigval) != -1); 44631.1Skamil 44641.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44651.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44661.1Skamil 44671.1Skamil validate_status_exited(status, exitval); 44681.1Skamil 44691.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44701.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 44711.1Skamil} 44721.1Skamil 44731.79Skamil#define PTRACE_SIGINFO(test, faked) \ 44741.79SkamilATF_TC(test); \ 44751.79SkamilATF_TC_HEAD(test, tc) \ 44761.79Skamil{ \ 44771.79Skamil atf_tc_set_md_var(tc, "descr", \ 44781.79Skamil "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls" \ 44791.79Skamil "with%s setting signal to new value", faked ? "" : "out"); \ 44801.79Skamil} \ 44811.79Skamil \ 44821.79Skamilstatic int test##_caught = 0; \ 44831.79Skamil \ 44841.79Skamilstatic void \ 44851.79Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx) \ 44861.79Skamil{ \ 44871.79Skamil if (faked) { \ 44881.79Skamil FORKEE_ASSERT_EQ(sig, SIGTRAP); \ 44891.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP); \ 44901.79Skamil FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT); \ 44911.79Skamil } else { \ 44921.79Skamil FORKEE_ASSERT_EQ(sig, SIGINT); \ 44931.79Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGINT); \ 44941.79Skamil FORKEE_ASSERT_EQ(info->si_code, SI_LWP); \ 44951.79Skamil } \ 44961.79Skamil \ 44971.79Skamil ++ test##_caught; \ 44981.79Skamil} \ 44991.79Skamil \ 45001.79SkamilATF_TC_BODY(test, tc) \ 45011.79Skamil{ \ 45021.79Skamil \ 45031.79Skamil ptrace_siginfo(faked, test##_sighandler, & test##_caught); \ 45041.79Skamil} 45051.79Skamil 45061.79SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false) 45071.79SkamilPTRACE_SIGINFO(siginfo_set_faked, true) 45081.79Skamil 45091.79Skamil/// ---------------------------------------------------------------------------- 45101.79Skamil 45111.82SkamilATF_TC(traceme_exec); 45121.82SkamilATF_TC_HEAD(traceme_exec, tc) 45131.1Skamil{ 45141.1Skamil atf_tc_set_md_var(tc, "descr", 45151.1Skamil "Detect SIGTRAP TRAP_EXEC from tracee"); 45161.1Skamil} 45171.1Skamil 45181.82SkamilATF_TC_BODY(traceme_exec, tc) 45191.1Skamil{ 45201.1Skamil const int sigval = SIGTRAP; 45211.1Skamil pid_t child, wpid; 45221.1Skamil#if defined(TWAIT_HAVE_STATUS) 45231.1Skamil int status; 45241.1Skamil#endif 45251.1Skamil 45261.1Skamil struct ptrace_siginfo info; 45271.1Skamil memset(&info, 0, sizeof(info)); 45281.1Skamil 45291.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 45301.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 45311.1Skamil if (child == 0) { 45321.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 45331.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 45341.1Skamil 45351.13Schristos DPRINTF("Before calling execve(2) from child\n"); 45361.1Skamil execlp("/bin/echo", "/bin/echo", NULL); 45371.1Skamil 45381.1Skamil FORKEE_ASSERT(0 && "Not reached"); 45391.1Skamil } 45401.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 45411.1Skamil 45421.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45431.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 45441.1Skamil 45451.1Skamil validate_status_stopped(status, sigval); 45461.1Skamil 45471.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 45481.61Skre SYSCALL_REQUIRE( 45491.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 45501.1Skamil 45511.13Schristos DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 45521.13Schristos DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 45531.1Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 45541.1Skamil info.psi_siginfo.si_errno); 45551.1Skamil 45561.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 45571.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 45581.1Skamil 45591.13Schristos DPRINTF("Before resuming the child process where it left off and " 45601.1Skamil "without signal to be sent\n"); 45611.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 45621.1Skamil 45631.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45641.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 45651.1Skamil 45661.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45671.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 45681.1Skamil} 45691.1Skamil 45701.82Skamil/// ---------------------------------------------------------------------------- 45711.82Skamil 45721.83Skamilstatic volatile int done; 45731.1Skamil 45741.83Skamilstatic void * 45751.83Skamiltrace_threads_cb(void *arg __unused) 45761.1Skamil{ 45771.1Skamil 45781.83Skamil done++; 45791.83Skamil 45801.83Skamil while (done < 3) 45811.83Skamil continue; 45821.83Skamil 45831.83Skamil return NULL; 45841.1Skamil} 45851.1Skamil 45861.83Skamilstatic void 45871.83Skamiltrace_threads(bool trace_create, bool trace_exit) 45881.1Skamil{ 45891.1Skamil const int sigval = SIGSTOP; 45901.1Skamil pid_t child, wpid; 45911.1Skamil#if defined(TWAIT_HAVE_STATUS) 45921.1Skamil int status; 45931.1Skamil#endif 45941.1Skamil ptrace_state_t state; 45951.1Skamil const int slen = sizeof(state); 45961.1Skamil ptrace_event_t event; 45971.1Skamil const int elen = sizeof(event); 45981.83Skamil struct ptrace_siginfo info; 45991.83Skamil 46001.83Skamil pthread_t t[3]; 46011.83Skamil int rv; 46021.83Skamil size_t n; 46031.1Skamil lwpid_t lid; 46041.83Skamil 46051.83Skamil /* Track created and exited threads */ 46061.83Skamil bool traced_lwps[__arraycount(t)]; 46071.83Skamil 46081.83Skamil atf_tc_skip("PR kern/51995"); 46091.1Skamil 46101.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 46111.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 46121.1Skamil if (child == 0) { 46131.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 46141.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 46151.1Skamil 46161.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 46171.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 46181.1Skamil 46191.83Skamil for (n = 0; n < __arraycount(t); n++) { 46201.83Skamil rv = pthread_create(&t[n], NULL, trace_threads_cb, 46211.83Skamil NULL); 46221.83Skamil FORKEE_ASSERT(rv == 0); 46231.83Skamil } 46241.1Skamil 46251.83Skamil for (n = 0; n < __arraycount(t); n++) { 46261.83Skamil rv = pthread_join(t[n], NULL); 46271.83Skamil FORKEE_ASSERT(rv == 0); 46281.83Skamil } 46291.1Skamil 46301.83Skamil /* 46311.83Skamil * There is race between _exit() and pthread_join() detaching 46321.83Skamil * a thread. For simplicity kill the process after detecting 46331.83Skamil * LWP events. 46341.83Skamil */ 46351.83Skamil while (true) 46361.83Skamil continue; 46371.1Skamil 46381.83Skamil FORKEE_ASSERT(0 && "Not reached"); 46391.1Skamil } 46401.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 46411.1Skamil 46421.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46431.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 46441.1Skamil 46451.1Skamil validate_status_stopped(status, sigval); 46461.1Skamil 46471.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 46481.83Skamil SYSCALL_REQUIRE( 46491.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 46501.1Skamil 46511.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 46521.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 46531.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 46541.83Skamil info.psi_siginfo.si_errno); 46551.1Skamil 46561.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 46571.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 46581.1Skamil 46591.83Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 46601.83Skamil memset(&event, 0, sizeof(event)); 46611.83Skamil if (trace_create) 46621.83Skamil event.pe_set_event |= PTRACE_LWP_CREATE; 46631.83Skamil if (trace_exit) 46641.83Skamil event.pe_set_event |= PTRACE_LWP_EXIT; 46651.83Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 46661.1Skamil 46671.13Schristos DPRINTF("Before resuming the child process where it left off and " 46681.1Skamil "without signal to be sent\n"); 46691.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 46701.1Skamil 46711.83Skamil memset(traced_lwps, 0, sizeof(traced_lwps)); 46721.1Skamil 46731.83Skamil for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) { 46741.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 46751.83Skamil "SIGTRAP\n", TWAIT_FNAME); 46761.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 46771.83Skamil child); 46781.1Skamil 46791.83Skamil validate_status_stopped(status, SIGTRAP); 46801.1Skamil 46811.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 46821.83Skamil "child\n"); 46831.83Skamil SYSCALL_REQUIRE( 46841.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 46851.1Skamil 46861.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 46871.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 46881.83Skamil "si_errno=%#x\n", 46891.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 46901.83Skamil info.psi_siginfo.si_errno); 46911.1Skamil 46921.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 46931.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 46941.1Skamil 46951.83Skamil SYSCALL_REQUIRE( 46961.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 46971.1Skamil 46981.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 46991.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 47001.1Skamil 47011.83Skamil lid = state.pe_lwp; 47021.83Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 47031.1Skamil 47041.83Skamil traced_lwps[lid - 1] = true; 47051.1Skamil 47061.83Skamil DPRINTF("Before resuming the child process where it left off " 47071.83Skamil "and without signal to be sent\n"); 47081.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 47091.83Skamil } 47101.1Skamil 47111.83Skamil for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) { 47121.83Skamil DPRINTF("Before calling %s() for the child - expected stopped " 47131.83Skamil "SIGTRAP\n", TWAIT_FNAME); 47141.83Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 47151.83Skamil child); 47161.1Skamil 47171.83Skamil validate_status_stopped(status, SIGTRAP); 47181.1Skamil 47191.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 47201.83Skamil "child\n"); 47211.83Skamil SYSCALL_REQUIRE( 47221.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 47231.1Skamil 47241.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 47251.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 47261.83Skamil "si_errno=%#x\n", 47271.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 47281.83Skamil info.psi_siginfo.si_errno); 47291.1Skamil 47301.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 47311.83Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 47321.1Skamil 47331.83Skamil SYSCALL_REQUIRE( 47341.83Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 47351.1Skamil 47361.83Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 47371.83Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 47381.1Skamil 47391.83Skamil lid = state.pe_lwp; 47401.83Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 47411.1Skamil 47421.83Skamil if (trace_create) { 47431.83Skamil ATF_REQUIRE(traced_lwps[lid - 1] == true); 47441.83Skamil traced_lwps[lid - 1] = false; 47451.83Skamil } 47461.1Skamil 47471.83Skamil DPRINTF("Before resuming the child process where it left off " 47481.83Skamil "and without signal to be sent\n"); 47491.83Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 47501.83Skamil } 47511.1Skamil 47521.83Skamil kill(child, SIGKILL); 47531.1Skamil 47541.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 47551.1Skamil TWAIT_FNAME); 47561.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 47571.1Skamil 47581.83Skamil validate_status_signaled(status, SIGKILL, 0); 47591.1Skamil 47601.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 47611.1Skamil TWAIT_FNAME); 47621.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 47631.1Skamil} 47641.1Skamil 47651.83Skamil#define TRACE_THREADS(test, trace_create, trace_exit) \ 47661.83SkamilATF_TC(test); \ 47671.83SkamilATF_TC_HEAD(test, tc) \ 47681.83Skamil{ \ 47691.83Skamil atf_tc_set_md_var(tc, "descr", \ 47701.83Skamil "Verify spawning threads with%s tracing LWP create and" \ 47711.83Skamil "with%s tracing LWP exit", trace_create ? "" : "out", \ 47721.83Skamil trace_exit ? "" : "out"); \ 47731.83Skamil} \ 47741.83Skamil \ 47751.83SkamilATF_TC_BODY(test, tc) \ 47761.83Skamil{ \ 47771.83Skamil \ 47781.83Skamil trace_threads(trace_create, trace_exit); \ 47791.83Skamil} 47801.83Skamil 47811.83SkamilTRACE_THREADS(trace_thread1, false, false) 47821.83SkamilTRACE_THREADS(trace_thread2, false, true) 47831.83SkamilTRACE_THREADS(trace_thread3, true, false) 47841.83SkamilTRACE_THREADS(trace_thread4, true, true) 47851.83Skamil 47861.83Skamil/// ---------------------------------------------------------------------------- 47871.83Skamil 47881.84SkamilATF_TC(signal_mask_unrelated); 47891.84SkamilATF_TC_HEAD(signal_mask_unrelated, tc) 47901.1Skamil{ 47911.1Skamil atf_tc_set_md_var(tc, "descr", 47921.1Skamil "Verify that masking single unrelated signal does not stop tracer " 47931.1Skamil "from catching other signals"); 47941.1Skamil} 47951.1Skamil 47961.84SkamilATF_TC_BODY(signal_mask_unrelated, tc) 47971.1Skamil{ 47981.1Skamil const int exitval = 5; 47991.1Skamil const int sigval = SIGSTOP; 48001.1Skamil const int sigmasked = SIGTRAP; 48011.1Skamil const int signotmasked = SIGINT; 48021.1Skamil pid_t child, wpid; 48031.1Skamil#if defined(TWAIT_HAVE_STATUS) 48041.1Skamil int status; 48051.1Skamil#endif 48061.1Skamil sigset_t intmask; 48071.1Skamil 48081.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 48091.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 48101.1Skamil if (child == 0) { 48111.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 48121.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 48131.1Skamil 48141.1Skamil sigemptyset(&intmask); 48151.1Skamil sigaddset(&intmask, sigmasked); 48161.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 48171.1Skamil 48181.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 48191.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 48201.1Skamil 48211.13Schristos DPRINTF("Before raising %s from child\n", 48221.1Skamil strsignal(signotmasked)); 48231.1Skamil FORKEE_ASSERT(raise(signotmasked) == 0); 48241.1Skamil 48251.13Schristos DPRINTF("Before exiting of the child process\n"); 48261.1Skamil _exit(exitval); 48271.1Skamil } 48281.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 48291.1Skamil 48301.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48311.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48321.1Skamil 48331.1Skamil validate_status_stopped(status, sigval); 48341.1Skamil 48351.13Schristos DPRINTF("Before resuming the child process where it left off and " 48361.1Skamil "without signal to be sent\n"); 48371.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 48381.1Skamil 48391.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48401.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48411.1Skamil 48421.1Skamil validate_status_stopped(status, signotmasked); 48431.1Skamil 48441.13Schristos DPRINTF("Before resuming the child process where it left off and " 48451.1Skamil "without signal to be sent\n"); 48461.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 48471.1Skamil 48481.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48491.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48501.1Skamil 48511.1Skamil validate_status_exited(status, exitval); 48521.1Skamil 48531.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48541.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 48551.1Skamil} 48561.1Skamil 48571.84Skamil/// ---------------------------------------------------------------------------- 48581.84Skamil 48591.1SkamilATF_TC(signal5); 48601.1SkamilATF_TC_HEAD(signal5, tc) 48611.1Skamil{ 48621.1Skamil atf_tc_set_md_var(tc, "descr", 48631.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 48641.1Skamil "catching exec() breakpoint"); 48651.1Skamil} 48661.1Skamil 48671.1SkamilATF_TC_BODY(signal5, tc) 48681.1Skamil{ 48691.1Skamil const int sigval = SIGSTOP; 48701.1Skamil const int sigmasked = SIGTRAP; 48711.1Skamil pid_t child, wpid; 48721.1Skamil#if defined(TWAIT_HAVE_STATUS) 48731.1Skamil int status; 48741.1Skamil#endif 48751.58Skamil struct ptrace_siginfo info; 48761.1Skamil sigset_t intmask; 48771.1Skamil 48781.58Skamil memset(&info, 0, sizeof(info)); 48791.14Schristos 48801.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 48811.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 48821.1Skamil if (child == 0) { 48831.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 48841.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 48851.1Skamil 48861.1Skamil sigemptyset(&intmask); 48871.1Skamil sigaddset(&intmask, sigmasked); 48881.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 48891.1Skamil 48901.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 48911.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 48921.1Skamil 48931.13Schristos DPRINTF("Before calling execve(2) from child\n"); 48941.1Skamil execlp("/bin/echo", "/bin/echo", NULL); 48951.1Skamil 48961.58Skamil /* NOTREACHED */ 48971.58Skamil FORKEE_ASSERTX(0 && "Not reached"); 48981.1Skamil } 48991.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 49001.1Skamil 49011.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49021.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 49031.1Skamil 49041.1Skamil validate_status_stopped(status, sigval); 49051.1Skamil 49061.13Schristos DPRINTF("Before resuming the child process where it left off and " 49071.1Skamil "without signal to be sent\n"); 49081.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 49091.1Skamil 49101.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49111.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 49121.1Skamil 49131.1Skamil validate_status_stopped(status, sigmasked); 49141.1Skamil 49151.58Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 49161.61Skre SYSCALL_REQUIRE( 49171.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 49181.58Skamil 49191.58Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 49201.58Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 49211.58Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 49221.58Skamil info.psi_siginfo.si_errno); 49231.58Skamil 49241.58Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigmasked); 49251.58Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 49261.58Skamil 49271.13Schristos DPRINTF("Before resuming the child process where it left off and " 49281.1Skamil "without signal to be sent\n"); 49291.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 49301.1Skamil 49311.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49321.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 49331.1Skamil 49341.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49351.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 49361.1Skamil} 49371.1Skamil 49381.1Skamil#if defined(TWAIT_HAVE_PID) 49391.1SkamilATF_TC(signal6); 49401.1SkamilATF_TC_HEAD(signal6, tc) 49411.1Skamil{ 49421.1Skamil atf_tc_set_md_var(tc, "timeout", "5"); 49431.1Skamil atf_tc_set_md_var(tc, "descr", 49441.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 49451.1Skamil "catching PTRACE_FORK breakpoint"); 49461.1Skamil} 49471.1Skamil 49481.1SkamilATF_TC_BODY(signal6, tc) 49491.1Skamil{ 49501.1Skamil const int exitval = 5; 49511.1Skamil const int exitval2 = 15; 49521.1Skamil const int sigval = SIGSTOP; 49531.1Skamil const int sigmasked = SIGTRAP; 49541.1Skamil pid_t child, child2, wpid; 49551.1Skamil#if defined(TWAIT_HAVE_STATUS) 49561.1Skamil int status; 49571.1Skamil#endif 49581.1Skamil sigset_t intmask; 49591.1Skamil ptrace_state_t state; 49601.1Skamil const int slen = sizeof(state); 49611.1Skamil ptrace_event_t event; 49621.1Skamil const int elen = sizeof(event); 49631.1Skamil 49641.38Skamil atf_tc_expect_fail("PR kern/51918"); 49651.14Schristos 49661.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 49671.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 49681.1Skamil if (child == 0) { 49691.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 49701.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 49711.1Skamil 49721.1Skamil sigemptyset(&intmask); 49731.1Skamil sigaddset(&intmask, sigmasked); 49741.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 49751.1Skamil 49761.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 49771.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 49781.1Skamil 49791.1Skamil FORKEE_ASSERT((child2 = fork()) != -1); 49801.1Skamil 49811.1Skamil if (child2 == 0) 49821.1Skamil _exit(exitval2); 49831.1Skamil 49841.1Skamil FORKEE_REQUIRE_SUCCESS 49851.1Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 49861.1Skamil 49871.1Skamil forkee_status_exited(status, exitval2); 49881.1Skamil 49891.13Schristos DPRINTF("Before exiting of the child process\n"); 49901.1Skamil _exit(exitval); 49911.1Skamil } 49921.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 49931.1Skamil 49941.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 49951.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 49961.1Skamil 49971.1Skamil validate_status_stopped(status, sigval); 49981.1Skamil 49991.13Schristos DPRINTF("Enable PTRACE_FORK in EVENT_MASK for the child %d\n", child); 50001.1Skamil event.pe_set_event = PTRACE_FORK; 50011.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 50021.1Skamil 50031.13Schristos DPRINTF("Before resuming the child process where it left off and " 50041.1Skamil "without signal to be sent\n"); 50051.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 50061.1Skamil 50071.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 50081.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 50091.1Skamil 50101.1Skamil validate_status_stopped(status, sigmasked); 50111.1Skamil 50121.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 50131.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK); 50141.1Skamil 50151.1Skamil child2 = state.pe_other_pid; 50161.13Schristos DPRINTF("Reported PTRACE_FORK event with forkee %d\n", child2); 50171.1Skamil 50181.13Schristos DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME); 50191.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 50201.1Skamil child2); 50211.1Skamil 50221.1Skamil validate_status_stopped(status, SIGTRAP); 50231.1Skamil 50241.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 50251.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_FORK); 50261.1Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 50271.1Skamil 50281.13Schristos DPRINTF("Before resuming the forkee process where it left off and " 50291.1Skamil "without signal to be sent\n"); 50301.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 50311.1Skamil 50321.13Schristos DPRINTF("Before resuming the child process where it left off and " 50331.1Skamil "without signal to be sent\n"); 50341.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 50351.1Skamil 50361.13Schristos DPRINTF("Before calling %s() for the forkee - expected exited\n", 50371.1Skamil TWAIT_FNAME); 50381.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 50391.57Skamil child2); 50401.1Skamil 50411.1Skamil validate_status_exited(status, exitval2); 50421.1Skamil 50431.13Schristos DPRINTF("Before calling %s() for the forkee - expected no process\n", 50441.1Skamil TWAIT_FNAME); 50451.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 50461.1Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 50471.1Skamil 50481.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 50491.1Skamil "SIGCHLD\n", TWAIT_FNAME); 50501.57Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 50511.1Skamil 50521.1Skamil validate_status_stopped(status, SIGCHLD); 50531.1Skamil 50541.57Skamil DPRINTF("Before resuming the child process where it left off and " 50551.1Skamil "without signal to be sent\n"); 50561.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 50571.1Skamil 50581.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 50591.1Skamil TWAIT_FNAME); 50601.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 50611.1Skamil 50621.1Skamil validate_status_exited(status, exitval); 50631.1Skamil 50641.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 50651.57Skamil TWAIT_FNAME); 50661.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 50671.1Skamil} 50681.1Skamil#endif 50691.1Skamil 50701.1Skamil#if defined(TWAIT_HAVE_PID) 50711.1SkamilATF_TC(signal7); 50721.1SkamilATF_TC_HEAD(signal7, tc) 50731.1Skamil{ 50741.1Skamil atf_tc_set_md_var(tc, "descr", 50751.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 50761.1Skamil "catching PTRACE_VFORK breakpoint"); 50771.1Skamil} 50781.1Skamil 50791.1SkamilATF_TC_BODY(signal7, tc) 50801.1Skamil{ 50811.1Skamil const int exitval = 5; 50821.1Skamil const int exitval2 = 15; 50831.1Skamil const int sigval = SIGSTOP; 50841.1Skamil const int sigmasked = SIGTRAP; 50851.1Skamil pid_t child, child2, wpid; 50861.1Skamil#if defined(TWAIT_HAVE_STATUS) 50871.1Skamil int status; 50881.1Skamil#endif 50891.1Skamil sigset_t intmask; 50901.1Skamil ptrace_state_t state; 50911.1Skamil const int slen = sizeof(state); 50921.1Skamil ptrace_event_t event; 50931.1Skamil const int elen = sizeof(event); 50941.1Skamil 50951.38Skamil atf_tc_expect_fail("PR kern/51918"); 50961.14Schristos 50971.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 50981.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 50991.1Skamil if (child == 0) { 51001.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 51011.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 51021.1Skamil 51031.1Skamil sigemptyset(&intmask); 51041.1Skamil sigaddset(&intmask, sigmasked); 51051.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 51061.1Skamil 51071.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 51081.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 51091.1Skamil 51101.1Skamil FORKEE_ASSERT((child2 = fork()) != -1); 51111.1Skamil 51121.1Skamil if (child2 == 0) 51131.1Skamil _exit(exitval2); 51141.1Skamil 51151.1Skamil FORKEE_REQUIRE_SUCCESS 51161.1Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 51171.1Skamil 51181.1Skamil forkee_status_exited(status, exitval2); 51191.1Skamil 51201.13Schristos DPRINTF("Before exiting of the child process\n"); 51211.1Skamil _exit(exitval); 51221.1Skamil } 51231.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 51241.1Skamil 51251.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51261.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 51271.1Skamil 51281.1Skamil validate_status_stopped(status, sigval); 51291.1Skamil 51301.13Schristos DPRINTF("Enable PTRACE_VFORK in EVENT_MASK for the child %d\n", child); 51311.1Skamil event.pe_set_event = PTRACE_VFORK; 51321.61Skre SYSCALL_REQUIRE( 51331.61Skre ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1 || 51341.61Skre errno == ENOTSUP); 51351.1Skamil 51361.13Schristos DPRINTF("Before resuming the child process where it left off and " 51371.1Skamil "without signal to be sent\n"); 51381.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 51391.1Skamil 51401.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 51411.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 51421.1Skamil 51431.1Skamil validate_status_stopped(status, sigmasked); 51441.1Skamil 51451.61Skre SYSCALL_REQUIRE( 51461.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 51471.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK); 51481.1Skamil 51491.1Skamil child2 = state.pe_other_pid; 51501.13Schristos DPRINTF("Reported PTRACE_VFORK event with forkee %d\n", child2); 51511.1Skamil 51521.13Schristos DPRINTF("Before calling %s() for the child2\n", TWAIT_FNAME); 51531.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 51541.1Skamil child2); 51551.1Skamil 51561.1Skamil validate_status_stopped(status, SIGTRAP); 51571.1Skamil 51581.61Skre SYSCALL_REQUIRE( 51591.61Skre ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1); 51601.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK); 51611.1Skamil ATF_REQUIRE_EQ(state.pe_other_pid, child); 51621.1Skamil 51631.13Schristos DPRINTF("Before resuming the forkee process where it left off and " 51641.1Skamil "without signal to be sent\n"); 51651.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1); 51661.1Skamil 51671.13Schristos DPRINTF("Before resuming the child process where it left off and " 51681.1Skamil "without signal to be sent\n"); 51691.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 51701.1Skamil 51711.13Schristos DPRINTF("Before calling %s() for the forkee - expected exited\n", 51721.1Skamil TWAIT_FNAME); 51731.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0), 51741.57Skamil child2); 51751.1Skamil 51761.1Skamil validate_status_exited(status, exitval2); 51771.1Skamil 51781.13Schristos DPRINTF("Before calling %s() for the forkee - expected no process\n", 51791.1Skamil TWAIT_FNAME); 51801.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 51811.1Skamil wpid = TWAIT_GENERIC(child2, &status, 0)); 51821.1Skamil 51831.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 51841.1Skamil "SIGCHLD\n", TWAIT_FNAME); 51851.57Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 51861.1Skamil 51871.1Skamil validate_status_stopped(status, SIGCHLD); 51881.1Skamil 51891.57Skamil DPRINTF("Before resuming the child process where it left off and " 51901.1Skamil "without signal to be sent\n"); 51911.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 51921.1Skamil 51931.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 51941.1Skamil TWAIT_FNAME); 51951.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 51961.1Skamil 51971.1Skamil validate_status_exited(status, exitval); 51981.1Skamil 51991.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 52001.57Skamil TWAIT_FNAME); 52011.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 52021.1Skamil} 52031.1Skamil#endif 52041.1Skamil 52051.1SkamilATF_TC(signal8); 52061.1SkamilATF_TC_HEAD(signal8, tc) 52071.1Skamil{ 52081.1Skamil atf_tc_set_md_var(tc, "descr", 52091.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 52101.1Skamil "catching PTRACE_VFORK_DONE breakpoint"); 52111.1Skamil} 52121.1Skamil 52131.1SkamilATF_TC_BODY(signal8, tc) 52141.1Skamil{ 52151.1Skamil const int exitval = 5; 52161.1Skamil const int exitval2 = 15; 52171.1Skamil const int sigval = SIGSTOP; 52181.1Skamil const int sigmasked = SIGTRAP; 52191.1Skamil pid_t child, child2, wpid; 52201.1Skamil#if defined(TWAIT_HAVE_STATUS) 52211.1Skamil int status; 52221.1Skamil#endif 52231.1Skamil sigset_t intmask; 52241.1Skamil ptrace_state_t state; 52251.1Skamil const int slen = sizeof(state); 52261.1Skamil ptrace_event_t event; 52271.1Skamil const int elen = sizeof(event); 52281.1Skamil 52291.14Schristos atf_tc_expect_fail("PR kern/51918"); 52301.14Schristos 52311.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 52321.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 52331.1Skamil if (child == 0) { 52341.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 52351.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 52361.1Skamil 52371.1Skamil sigemptyset(&intmask); 52381.1Skamil sigaddset(&intmask, sigmasked); 52391.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 52401.1Skamil 52411.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 52421.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 52431.1Skamil 52441.1Skamil FORKEE_ASSERT((child2 = vfork()) != -1); 52451.1Skamil 52461.1Skamil if (child2 == 0) 52471.1Skamil _exit(exitval2); 52481.1Skamil 52491.1Skamil FORKEE_REQUIRE_SUCCESS 52501.1Skamil (wpid = TWAIT_GENERIC(child2, &status, 0), child2); 52511.1Skamil 52521.1Skamil forkee_status_exited(status, exitval2); 52531.1Skamil 52541.13Schristos DPRINTF("Before exiting of the child process\n"); 52551.1Skamil _exit(exitval); 52561.1Skamil } 52571.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 52581.1Skamil 52591.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52601.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52611.1Skamil 52621.1Skamil validate_status_stopped(status, sigval); 52631.1Skamil 52641.13Schristos DPRINTF("Enable PTRACE_VFORK_DONE in EVENT_MASK for the child %d\n", 52651.1Skamil child); 52661.1Skamil event.pe_set_event = PTRACE_VFORK_DONE; 52671.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 52681.1Skamil 52691.13Schristos DPRINTF("Before resuming the child process where it left off and " 52701.1Skamil "without signal to be sent\n"); 52711.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 52721.1Skamil 52731.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 52741.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52751.1Skamil 52761.1Skamil validate_status_stopped(status, sigmasked); 52771.1Skamil 52781.61Skre SYSCALL_REQUIRE( 52791.61Skre ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 52801.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE); 52811.1Skamil 52821.1Skamil child2 = state.pe_other_pid; 52831.13Schristos DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n", child2); 52841.1Skamil 52851.13Schristos DPRINTF("Before resuming the child process where it left off and " 52861.1Skamil "without signal to be sent\n"); 52871.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 52881.1Skamil 52891.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 52901.1Skamil "SIGCHLD\n", TWAIT_FNAME); 52911.57Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 52921.1Skamil 52931.1Skamil validate_status_stopped(status, SIGCHLD); 52941.1Skamil 52951.57Skamil DPRINTF("Before resuming the child process where it left off and " 52961.1Skamil "without signal to be sent\n"); 52971.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 52981.1Skamil 52991.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 53001.1Skamil TWAIT_FNAME); 53011.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 53021.1Skamil 53031.1Skamil validate_status_exited(status, exitval); 53041.1Skamil 53051.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 53061.57Skamil TWAIT_FNAME); 53071.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 53081.1Skamil} 53091.1Skamil 53101.83Skamilvolatile lwpid_t the_lwp_id = 0; 53111.83Skamil 53121.83Skamilstatic void 53131.83Skamillwp_main_func(void *arg) 53141.83Skamil{ 53151.83Skamil the_lwp_id = _lwp_self(); 53161.83Skamil _lwp_exit(); 53171.83Skamil} 53181.83Skamil 53191.1SkamilATF_TC(signal9); 53201.1SkamilATF_TC_HEAD(signal9, tc) 53211.1Skamil{ 53221.1Skamil atf_tc_set_md_var(tc, "descr", 53231.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 53241.1Skamil "catching PTRACE_LWP_CREATE breakpoint"); 53251.1Skamil} 53261.1Skamil 53271.1SkamilATF_TC_BODY(signal9, tc) 53281.1Skamil{ 53291.1Skamil const int exitval = 5; 53301.1Skamil const int sigval = SIGSTOP; 53311.1Skamil const int sigmasked = SIGTRAP; 53321.1Skamil pid_t child, wpid; 53331.1Skamil#if defined(TWAIT_HAVE_STATUS) 53341.1Skamil int status; 53351.1Skamil#endif 53361.1Skamil sigset_t intmask; 53371.1Skamil ptrace_state_t state; 53381.1Skamil const int slen = sizeof(state); 53391.1Skamil ptrace_event_t event; 53401.1Skamil const int elen = sizeof(event); 53411.1Skamil ucontext_t uc; 53421.1Skamil lwpid_t lid; 53431.1Skamil static const size_t ssize = 16*1024; 53441.1Skamil void *stack; 53451.1Skamil 53461.14Schristos atf_tc_expect_fail("PR kern/51918"); 53471.14Schristos 53481.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 53491.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 53501.1Skamil if (child == 0) { 53511.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 53521.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 53531.1Skamil 53541.1Skamil sigemptyset(&intmask); 53551.1Skamil sigaddset(&intmask, sigmasked); 53561.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 53571.1Skamil 53581.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 53591.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 53601.1Skamil 53611.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 53621.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 53631.1Skamil 53641.13Schristos DPRINTF("Before making context for new lwp in child\n"); 53651.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 53661.1Skamil 53671.13Schristos DPRINTF("Before creating new in child\n"); 53681.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 53691.1Skamil 53701.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 53711.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 53721.1Skamil 53731.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 53741.1Skamil "are the same\n", lid, the_lwp_id); 53751.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 53761.1Skamil 53771.13Schristos DPRINTF("Before exiting of the child process\n"); 53781.1Skamil _exit(exitval); 53791.1Skamil } 53801.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 53811.1Skamil 53821.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 53831.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 53841.1Skamil 53851.1Skamil validate_status_stopped(status, sigval); 53861.1Skamil 53871.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 53881.1Skamil event.pe_set_event = PTRACE_LWP_CREATE; 53891.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 53901.1Skamil 53911.13Schristos DPRINTF("Before resuming the child process where it left off and " 53921.1Skamil "without signal to be sent\n"); 53931.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 53941.1Skamil 53951.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 53961.1Skamil "SIGTRAP\n", TWAIT_FNAME); 53971.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 53981.1Skamil 53991.1Skamil validate_status_stopped(status, sigmasked); 54001.1Skamil 54011.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 54021.1Skamil 54031.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE); 54041.1Skamil 54051.1Skamil lid = state.pe_lwp; 54061.13Schristos DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 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 - expected exited\n", 54131.1Skamil TWAIT_FNAME); 54141.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 54151.1Skamil 54161.1Skamil validate_status_exited(status, exitval); 54171.1Skamil 54181.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 54191.1Skamil TWAIT_FNAME); 54201.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 54211.1Skamil} 54221.1Skamil 54231.1SkamilATF_TC(signal10); 54241.1SkamilATF_TC_HEAD(signal10, tc) 54251.1Skamil{ 54261.1Skamil atf_tc_set_md_var(tc, "descr", 54271.1Skamil "Verify that masking SIGTRAP in tracee does not stop tracer from " 54281.1Skamil "catching PTRACE_LWP_EXIT breakpoint"); 54291.1Skamil} 54301.1Skamil 54311.1SkamilATF_TC_BODY(signal10, tc) 54321.1Skamil{ 54331.1Skamil const int exitval = 5; 54341.1Skamil const int sigval = SIGSTOP; 54351.1Skamil const int sigmasked = SIGTRAP; 54361.1Skamil pid_t child, wpid; 54371.1Skamil#if defined(TWAIT_HAVE_STATUS) 54381.1Skamil int status; 54391.1Skamil#endif 54401.1Skamil sigset_t intmask; 54411.1Skamil ptrace_state_t state; 54421.1Skamil const int slen = sizeof(state); 54431.1Skamil ptrace_event_t event; 54441.1Skamil const int elen = sizeof(event); 54451.1Skamil ucontext_t uc; 54461.1Skamil lwpid_t lid; 54471.1Skamil static const size_t ssize = 16*1024; 54481.1Skamil void *stack; 54491.1Skamil 54501.14Schristos atf_tc_expect_fail("PR kern/51918"); 54511.14Schristos 54521.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 54531.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 54541.1Skamil if (child == 0) { 54551.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 54561.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 54571.1Skamil 54581.1Skamil sigemptyset(&intmask); 54591.1Skamil sigaddset(&intmask, sigmasked); 54601.1Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 54611.1Skamil 54621.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 54631.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 54641.1Skamil 54651.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 54661.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 54671.1Skamil 54681.13Schristos DPRINTF("Before making context for new lwp in child\n"); 54691.1Skamil _lwp_makecontext(&uc, lwp_main_func, NULL, NULL, stack, ssize); 54701.1Skamil 54711.13Schristos DPRINTF("Before creating new in child\n"); 54721.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 54731.1Skamil 54741.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 54751.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 54761.1Skamil 54771.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 54781.1Skamil "are the same\n", lid, the_lwp_id); 54791.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 54801.1Skamil 54811.13Schristos DPRINTF("Before exiting of the child process\n"); 54821.1Skamil _exit(exitval); 54831.1Skamil } 54841.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 54851.1Skamil 54861.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 54871.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 54881.1Skamil 54891.1Skamil validate_status_stopped(status, sigval); 54901.1Skamil 54911.13Schristos DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 54921.1Skamil event.pe_set_event = PTRACE_LWP_EXIT; 54931.13Schristos SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 54941.1Skamil 54951.13Schristos DPRINTF("Before resuming the child process where it left off and " 54961.1Skamil "without signal to be sent\n"); 54971.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 54981.1Skamil 54991.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 55001.1Skamil "SIGTRAP\n", TWAIT_FNAME); 55011.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 55021.1Skamil 55031.1Skamil validate_status_stopped(status, sigmasked); 55041.1Skamil 55051.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 55061.1Skamil 55071.1Skamil ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_EXIT); 55081.1Skamil 55091.1Skamil lid = state.pe_lwp; 55101.13Schristos DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 55111.1Skamil 55121.13Schristos DPRINTF("Before resuming the child process where it left off and " 55131.1Skamil "without signal to be sent\n"); 55141.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 55151.1Skamil 55161.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 55171.1Skamil TWAIT_FNAME); 55181.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 55191.1Skamil 55201.1Skamil validate_status_exited(status, exitval); 55211.1Skamil 55221.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 55231.1Skamil TWAIT_FNAME); 55241.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 55251.1Skamil} 55261.1Skamil 55271.1Skamilstatic void 55281.1Skamillwp_main_stop(void *arg) 55291.1Skamil{ 55301.1Skamil the_lwp_id = _lwp_self(); 55311.1Skamil 55321.1Skamil raise(SIGTRAP); 55331.1Skamil 55341.1Skamil _lwp_exit(); 55351.1Skamil} 55361.1Skamil 55371.1SkamilATF_TC(suspend1); 55381.1SkamilATF_TC_HEAD(suspend1, tc) 55391.1Skamil{ 55401.1Skamil atf_tc_set_md_var(tc, "descr", 55411.1Skamil "Verify that a thread can be suspended by a debugger and later " 55421.1Skamil "resumed by a tracee"); 55431.1Skamil} 55441.1Skamil 55451.1SkamilATF_TC_BODY(suspend1, tc) 55461.1Skamil{ 55471.1Skamil const int exitval = 5; 55481.1Skamil const int sigval = SIGSTOP; 55491.1Skamil pid_t child, wpid; 55501.1Skamil#if defined(TWAIT_HAVE_STATUS) 55511.1Skamil int status; 55521.1Skamil#endif 55531.1Skamil ucontext_t uc; 55541.1Skamil lwpid_t lid; 55551.1Skamil static const size_t ssize = 16*1024; 55561.1Skamil void *stack; 55571.1Skamil struct ptrace_lwpinfo pl; 55581.1Skamil struct ptrace_siginfo psi; 55591.1Skamil volatile int go = 0; 55601.1Skamil 55611.17Skamil // Feature pending for refactoring 55621.17Skamil atf_tc_expect_fail("PR kern/51995"); 55631.17Skamil 55641.16Skamil // Hangs with qemu 55651.16Skamil ATF_REQUIRE(0 && "In order to get reliable failure, abort"); 55661.16Skamil 55671.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 55681.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 55691.1Skamil if (child == 0) { 55701.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 55711.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 55721.1Skamil 55731.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 55741.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 55751.1Skamil 55761.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 55771.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 55781.1Skamil 55791.13Schristos DPRINTF("Before making context for new lwp in child\n"); 55801.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 55811.1Skamil 55821.13Schristos DPRINTF("Before creating new in child\n"); 55831.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 55841.1Skamil 55851.1Skamil while (go == 0) 55861.1Skamil continue; 55871.1Skamil 55881.1Skamil raise(SIGINT); 55891.1Skamil 55901.1Skamil FORKEE_ASSERT(_lwp_continue(lid) == 0); 55911.1Skamil 55921.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 55931.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 55941.1Skamil 55951.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 55961.1Skamil "are the same\n", lid, the_lwp_id); 55971.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 55981.1Skamil 55991.13Schristos DPRINTF("Before exiting of the child process\n"); 56001.1Skamil _exit(exitval); 56011.1Skamil } 56021.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 56031.1Skamil 56041.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 56051.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56061.1Skamil 56071.1Skamil validate_status_stopped(status, sigval); 56081.1Skamil 56091.13Schristos DPRINTF("Before resuming the child process where it left off and " 56101.1Skamil "without signal to be sent\n"); 56111.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56121.1Skamil 56131.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 56141.1Skamil "SIGTRAP\n", TWAIT_FNAME); 56151.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56161.1Skamil 56171.1Skamil validate_status_stopped(status, SIGTRAP); 56181.1Skamil 56191.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 56201.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 56211.1Skamil 56221.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 56231.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 56241.1Skamil 56251.13Schristos DPRINTF("Write new go to tracee (PID=%d) from tracer (PID=%d)\n", 56261.1Skamil child, getpid()); 56271.13Schristos SYSCALL_REQUIRE(ptrace(PT_WRITE_D, child, __UNVOLATILE(&go), 1) != -1); 56281.1Skamil 56291.13Schristos DPRINTF("Before resuming the child process where it left off and " 56301.1Skamil "without signal to be sent\n"); 56311.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56321.1Skamil 56331.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 56341.1Skamil "SIGINT\n", TWAIT_FNAME); 56351.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56361.1Skamil 56371.1Skamil validate_status_stopped(status, SIGINT); 56381.1Skamil 56391.1Skamil pl.pl_lwpid = 0; 56401.1Skamil 56411.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 56421.1Skamil while (pl.pl_lwpid != 0) { 56431.1Skamil 56441.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 56451.1Skamil switch (pl.pl_lwpid) { 56461.1Skamil case 1: 56471.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 56481.1Skamil break; 56491.1Skamil case 2: 56501.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 56511.1Skamil break; 56521.1Skamil } 56531.1Skamil } 56541.1Skamil 56551.13Schristos DPRINTF("Before resuming the child process where it left off and " 56561.1Skamil "without signal to be sent\n"); 56571.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 56581.1Skamil 56591.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 56601.1Skamil TWAIT_FNAME); 56611.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 56621.1Skamil 56631.1Skamil validate_status_exited(status, exitval); 56641.1Skamil 56651.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 56661.1Skamil TWAIT_FNAME); 56671.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 56681.1Skamil} 56691.1Skamil 56701.1SkamilATF_TC(suspend2); 56711.1SkamilATF_TC_HEAD(suspend2, tc) 56721.1Skamil{ 56731.1Skamil atf_tc_set_md_var(tc, "descr", 56741.1Skamil "Verify that the while the only thread within a process is " 56751.1Skamil "suspended, the whole process cannot be unstopped"); 56761.1Skamil} 56771.1Skamil 56781.1SkamilATF_TC_BODY(suspend2, tc) 56791.1Skamil{ 56801.1Skamil const int exitval = 5; 56811.1Skamil const int sigval = SIGSTOP; 56821.1Skamil pid_t child, wpid; 56831.1Skamil#if defined(TWAIT_HAVE_STATUS) 56841.1Skamil int status; 56851.1Skamil#endif 56861.1Skamil struct ptrace_siginfo psi; 56871.1Skamil 56881.17Skamil // Feature pending for refactoring 56891.17Skamil atf_tc_expect_fail("PR kern/51995"); 56901.17Skamil 56911.16Skamil // Hangs with qemu 56921.16Skamil ATF_REQUIRE(0 && "In order to get reliable failure, abort"); 56931.16Skamil 56941.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 56951.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 56961.1Skamil if (child == 0) { 56971.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 56981.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 56991.1Skamil 57001.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 57011.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 57021.1Skamil 57031.13Schristos DPRINTF("Before exiting of the child process\n"); 57041.1Skamil _exit(exitval); 57051.1Skamil } 57061.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 57071.1Skamil 57081.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 57091.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57101.1Skamil 57111.1Skamil validate_status_stopped(status, sigval); 57121.1Skamil 57131.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 57141.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 57151.1Skamil 57161.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 57171.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 57181.1Skamil 57191.13Schristos DPRINTF("Before resuming the child process where it left off and " 57201.1Skamil "without signal to be sent\n"); 57211.1Skamil ATF_REQUIRE_ERRNO(EDEADLK, 57221.1Skamil ptrace(PT_CONTINUE, child, (void *)1, 0) == -1); 57231.1Skamil 57241.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 57251.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 57261.1Skamil 57271.13Schristos DPRINTF("Before resuming the child process where it left off and " 57281.1Skamil "without signal to be sent\n"); 57291.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 57301.1Skamil 57311.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 57321.1Skamil TWAIT_FNAME); 57331.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 57341.1Skamil 57351.1Skamil validate_status_exited(status, exitval); 57361.1Skamil 57371.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 57381.1Skamil TWAIT_FNAME); 57391.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 57401.1Skamil} 57411.1Skamil 57421.1SkamilATF_TC(resume1); 57431.1SkamilATF_TC_HEAD(resume1, tc) 57441.1Skamil{ 57451.1Skamil atf_tc_set_md_var(tc, "timeout", "5"); 57461.1Skamil atf_tc_set_md_var(tc, "descr", 57471.1Skamil "Verify that a thread can be suspended by a debugger and later " 57481.1Skamil "resumed by the debugger"); 57491.1Skamil} 57501.1Skamil 57511.1SkamilATF_TC_BODY(resume1, tc) 57521.1Skamil{ 57531.1Skamil struct msg_fds fds; 57541.1Skamil const int exitval = 5; 57551.1Skamil const int sigval = SIGSTOP; 57561.1Skamil pid_t child, wpid; 57571.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 57581.1Skamil#if defined(TWAIT_HAVE_STATUS) 57591.1Skamil int status; 57601.1Skamil#endif 57611.1Skamil ucontext_t uc; 57621.1Skamil lwpid_t lid; 57631.1Skamil static const size_t ssize = 16*1024; 57641.1Skamil void *stack; 57651.1Skamil struct ptrace_lwpinfo pl; 57661.1Skamil struct ptrace_siginfo psi; 57671.1Skamil 57681.17Skamil // Feature pending for refactoring 57691.17Skamil atf_tc_expect_fail("PR kern/51995"); 57701.17Skamil 57711.15Schristos // Hangs with qemu 57721.15Schristos ATF_REQUIRE(0 && "In order to get reliable failure, abort"); 57731.1Skamil 57741.13Schristos SYSCALL_REQUIRE(msg_open(&fds) == 0); 57751.1Skamil 57761.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 57771.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 57781.1Skamil if (child == 0) { 57791.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 57801.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 57811.1Skamil 57821.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 57831.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 57841.1Skamil 57851.13Schristos DPRINTF("Before allocating memory for stack in child\n"); 57861.1Skamil FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 57871.1Skamil 57881.13Schristos DPRINTF("Before making context for new lwp in child\n"); 57891.1Skamil _lwp_makecontext(&uc, lwp_main_stop, NULL, NULL, stack, ssize); 57901.1Skamil 57911.13Schristos DPRINTF("Before creating new in child\n"); 57921.1Skamil FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 57931.1Skamil 57941.1Skamil CHILD_TO_PARENT("Message", fds, msg); 57951.1Skamil 57961.1Skamil raise(SIGINT); 57971.1Skamil 57981.13Schristos DPRINTF("Before waiting for lwp %d to exit\n", lid); 57991.1Skamil FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 58001.1Skamil 58011.13Schristos DPRINTF("Before verifying that reported %d and running lid %d " 58021.1Skamil "are the same\n", lid, the_lwp_id); 58031.1Skamil FORKEE_ASSERT_EQ(lid, the_lwp_id); 58041.1Skamil 58051.13Schristos DPRINTF("Before exiting of the child process\n"); 58061.1Skamil _exit(exitval); 58071.1Skamil } 58081.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 58091.1Skamil 58101.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 58111.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 58121.1Skamil 58131.1Skamil validate_status_stopped(status, sigval); 58141.1Skamil 58151.13Schristos DPRINTF("Before resuming the child process where it left off and " 58161.1Skamil "without signal to be sent\n"); 58171.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 58181.1Skamil 58191.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 58201.1Skamil "SIGTRAP\n", TWAIT_FNAME); 58211.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 58221.1Skamil 58231.1Skamil validate_status_stopped(status, SIGTRAP); 58241.1Skamil 58251.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 58261.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 58271.1Skamil 58281.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 58291.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 58301.1Skamil 58311.1Skamil PARENT_FROM_CHILD("Message", fds, msg); 58321.1Skamil 58331.13Schristos DPRINTF("Before resuming the child process where it left off and " 58341.1Skamil "without signal to be sent\n"); 58351.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 58361.1Skamil 58371.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 58381.1Skamil "SIGINT\n", TWAIT_FNAME); 58391.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 58401.1Skamil 58411.1Skamil validate_status_stopped(status, SIGINT); 58421.1Skamil 58431.1Skamil pl.pl_lwpid = 0; 58441.1Skamil 58451.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 58461.1Skamil while (pl.pl_lwpid != 0) { 58471.13Schristos SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &pl, sizeof(pl)) != -1); 58481.1Skamil switch (pl.pl_lwpid) { 58491.1Skamil case 1: 58501.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SIGNAL); 58511.1Skamil break; 58521.1Skamil case 2: 58531.1Skamil ATF_REQUIRE_EQ(pl.pl_event, PL_EVENT_SUSPENDED); 58541.1Skamil break; 58551.1Skamil } 58561.1Skamil } 58571.1Skamil 58581.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 58591.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 58601.1Skamil 58611.13Schristos DPRINTF("Before resuming the child process where it left off and " 58621.1Skamil "without signal to be sent\n"); 58631.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 58641.1Skamil 58651.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 58661.1Skamil TWAIT_FNAME); 58671.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 58681.1Skamil 58691.1Skamil validate_status_exited(status, exitval); 58701.1Skamil 58711.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 58721.1Skamil TWAIT_FNAME); 58731.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 58741.1Skamil 58751.1Skamil msg_close(&fds); 58761.1Skamil 58771.13Schristos DPRINTF("XXX: Test worked this time but for consistency timeout it\n"); 58781.1Skamil sleep(10); 58791.1Skamil} 58801.1Skamil 58811.1SkamilATF_TC(syscall1); 58821.1SkamilATF_TC_HEAD(syscall1, tc) 58831.1Skamil{ 58841.1Skamil atf_tc_set_md_var(tc, "descr", 58851.1Skamil "Verify that getpid(2) can be traced with PT_SYSCALL"); 58861.1Skamil} 58871.1Skamil 58881.1SkamilATF_TC_BODY(syscall1, tc) 58891.1Skamil{ 58901.1Skamil const int exitval = 5; 58911.1Skamil const int sigval = SIGSTOP; 58921.1Skamil pid_t child, wpid; 58931.1Skamil#if defined(TWAIT_HAVE_STATUS) 58941.1Skamil int status; 58951.1Skamil#endif 58961.1Skamil struct ptrace_siginfo info; 58971.1Skamil memset(&info, 0, sizeof(info)); 58981.1Skamil 58991.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 59001.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 59011.1Skamil if (child == 0) { 59021.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 59031.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 59041.1Skamil 59051.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 59061.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 59071.1Skamil 59081.1Skamil syscall(SYS_getpid); 59091.1Skamil 59101.13Schristos DPRINTF("Before exiting of the child process\n"); 59111.1Skamil _exit(exitval); 59121.1Skamil } 59131.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 59141.1Skamil 59151.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 59161.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 59171.1Skamil 59181.1Skamil validate_status_stopped(status, sigval); 59191.1Skamil 59201.13Schristos DPRINTF("Before resuming the child process where it left off and " 59211.1Skamil "without signal to be sent\n"); 59221.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 59231.1Skamil 59241.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 59251.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 59261.1Skamil 59271.1Skamil validate_status_stopped(status, SIGTRAP); 59281.1Skamil 59291.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 59301.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 59311.1Skamil 59321.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 59331.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 59341.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 59351.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCE); 59361.1Skamil 59371.13Schristos DPRINTF("Before resuming the child process where it left off and " 59381.1Skamil "without signal to be sent\n"); 59391.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 59401.1Skamil 59411.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 59421.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 59431.1Skamil 59441.1Skamil validate_status_stopped(status, SIGTRAP); 59451.1Skamil 59461.13Schristos DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 59471.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 59481.1Skamil 59491.38Skamil DPRINTF("Before checking siginfo_t and lwpid\n"); 59501.38Skamil ATF_REQUIRE_EQ(info.psi_lwpid, 1); 59511.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 59521.1Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_SCX); 59531.1Skamil 59541.13Schristos DPRINTF("Before resuming the child process where it left off and " 59551.1Skamil "without signal to be sent\n"); 59561.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 59571.1Skamil 59581.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 59591.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 59601.1Skamil 59611.1Skamil validate_status_exited(status, exitval); 59621.1Skamil 59631.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 59641.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 59651.1Skamil} 59661.1Skamil 59671.1SkamilATF_TC(syscallemu1); 59681.1SkamilATF_TC_HEAD(syscallemu1, tc) 59691.1Skamil{ 59701.1Skamil atf_tc_set_md_var(tc, "descr", 59711.1Skamil "Verify that exit(2) can be intercepted with PT_SYSCALLEMU"); 59721.1Skamil} 59731.1Skamil 59741.1SkamilATF_TC_BODY(syscallemu1, tc) 59751.1Skamil{ 59761.1Skamil const int exitval = 5; 59771.1Skamil const int sigval = SIGSTOP; 59781.1Skamil pid_t child, wpid; 59791.1Skamil#if defined(TWAIT_HAVE_STATUS) 59801.1Skamil int status; 59811.1Skamil#endif 59821.1Skamil 59831.6Skamil#if defined(__sparc__) && !defined(__sparc64__) 59841.6Skamil /* syscallemu does not work on sparc (32-bit) */ 59851.6Skamil atf_tc_expect_fail("PR kern/52166"); 59861.6Skamil#endif 59871.6Skamil 59881.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 59891.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 59901.1Skamil if (child == 0) { 59911.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 59921.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 59931.1Skamil 59941.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 59951.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 59961.1Skamil 59971.1Skamil syscall(SYS_exit, 100); 59981.1Skamil 59991.13Schristos DPRINTF("Before exiting of the child process\n"); 60001.1Skamil _exit(exitval); 60011.1Skamil } 60021.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 60031.1Skamil 60041.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 60051.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60061.1Skamil 60071.1Skamil validate_status_stopped(status, sigval); 60081.1Skamil 60091.13Schristos DPRINTF("Before resuming the child process where it left off and " 60101.1Skamil "without signal to be sent\n"); 60111.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 60121.1Skamil 60131.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 60141.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60151.1Skamil 60161.1Skamil validate_status_stopped(status, SIGTRAP); 60171.1Skamil 60181.13Schristos DPRINTF("Set SYSCALLEMU for intercepted syscall\n"); 60191.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALLEMU, child, (void *)1, 0) != -1); 60201.1Skamil 60211.13Schristos DPRINTF("Before resuming the child process where it left off and " 60221.1Skamil "without signal to be sent\n"); 60231.13Schristos SYSCALL_REQUIRE(ptrace(PT_SYSCALL, child, (void *)1, 0) != -1); 60241.1Skamil 60251.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 60261.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60271.1Skamil 60281.1Skamil validate_status_stopped(status, SIGTRAP); 60291.1Skamil 60301.13Schristos DPRINTF("Before resuming the child process where it left off and " 60311.1Skamil "without signal to be sent\n"); 60321.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 60331.1Skamil 60341.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 60351.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 60361.1Skamil 60371.1Skamil validate_status_exited(status, exitval); 60381.1Skamil 60391.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 60401.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 60411.1Skamil} 60421.1Skamil 60431.1Skamil#include "t_ptrace_amd64_wait.h" 60441.1Skamil#include "t_ptrace_i386_wait.h" 60451.1Skamil#include "t_ptrace_x86_wait.h" 60461.1Skamil 60471.1SkamilATF_TP_ADD_TCS(tp) 60481.1Skamil{ 60491.1Skamil setvbuf(stdout, NULL, _IONBF, 0); 60501.1Skamil setvbuf(stderr, NULL, _IONBF, 0); 60511.33Skamil 60521.36Skamil ATF_TP_ADD_TC(tp, traceme_raise1); 60531.33Skamil ATF_TP_ADD_TC(tp, traceme_raise2); 60541.33Skamil ATF_TP_ADD_TC(tp, traceme_raise3); 60551.33Skamil ATF_TP_ADD_TC(tp, traceme_raise4); 60561.33Skamil ATF_TP_ADD_TC(tp, traceme_raise5); 60571.85Skamil ATF_TP_ADD_TC(tp, traceme_raise6); 60581.85Skamil ATF_TP_ADD_TC(tp, traceme_raise7); 60591.85Skamil ATF_TP_ADD_TC(tp, traceme_raise8); 60601.85Skamil ATF_TP_ADD_TC(tp, traceme_raise9); 60611.85Skamil ATF_TP_ADD_TC(tp, traceme_raise10); 60621.33Skamil 60631.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1); 60641.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2); 60651.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3); 60661.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4); 60671.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5); 60681.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6); 60691.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7); 60701.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8); 60711.87Skamil 60721.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1); 60731.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2); 60741.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3); 60751.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4); 60761.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5); 60771.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6); 60781.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7); 60791.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8); 60801.86Skamil 60811.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_trap); 60821.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_segv); 60831.71Skamil ATF_TP_ADD_TC(tp, traceme_crash_ill); 60841.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_fpe); 60851.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_bus); 60861.59Skamil 60871.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap); 60881.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv); 60891.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill); 60901.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe); 60911.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus); 60921.88Skamil 60931.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap); 60941.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv); 60951.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill); 60961.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe); 60971.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus); 60981.88Skamil 60991.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1); 61001.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2); 61011.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3); 61021.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4); 61031.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5); 61041.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6); 61051.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7); 61061.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8); 61071.50Skamil 61081.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1); 61091.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2); 61101.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3); 61111.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4); 61121.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5); 61131.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6); 61141.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7); 61151.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8); 61161.50Skamil 61171.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1); 61181.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2); 61191.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3); 61201.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4); 61211.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5); 61221.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6); 61231.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7); 61241.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8); 61251.50Skamil 61261.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1); 61271.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2); 61281.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3); 61291.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4); 61301.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5); 61311.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6); 61321.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7); 61331.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8); 61341.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9); 61351.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10); 61361.1Skamil 61371.37Skamil ATF_TP_ADD_TC(tp, traceme_pid1_parent); 61381.37Skamil 61391.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise1); 61401.46Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise2); 61411.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise3); 61421.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise4); 61431.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise5); 61441.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise6); 61451.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise7); 61461.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise8); 61471.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise9); 61481.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise10); 61491.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise11); 61501.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise12); 61511.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise13); 61521.40Skamil 61531.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap); 61541.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv); 61551.71Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill); 61561.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe); 61571.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus); 61581.41Skamil 61591.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap); 61601.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv); 61611.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill); 61621.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe); 61631.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus); 61641.92Skamil 61651.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap); 61661.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv); 61671.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill); 61681.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe); 61691.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus); 61701.92Skamil 61711.43Skamil ATF_TP_ADD_TC(tp, traceme_vfork_exec); 61721.43Skamil 61731.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap); 61741.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv); 61751.71Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill); 61761.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe); 61771.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus); 61781.59Skamil 61791.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 61801.94Skamil unrelated_tracer_sees_signalmasked_crash_trap); 61811.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 61821.94Skamil unrelated_tracer_sees_signalmasked_crash_segv); 61831.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 61841.94Skamil unrelated_tracer_sees_signalmasked_crash_ill); 61851.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 61861.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe); 61871.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 61881.94Skamil unrelated_tracer_sees_signalmasked_crash_bus); 61891.94Skamil 61901.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 61911.94Skamil unrelated_tracer_sees_signalignored_crash_trap); 61921.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 61931.94Skamil unrelated_tracer_sees_signalignored_crash_segv); 61941.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 61951.94Skamil unrelated_tracer_sees_signalignored_crash_ill); 61961.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 61971.94Skamil unrelated_tracer_sees_signalignored_crash_fpe); 61981.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 61991.94Skamil unrelated_tracer_sees_signalignored_crash_bus); 62001.94Skamil 62011.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent); 62021.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates); 62031.61Skre ATF_TP_ADD_TC_HAVE_PID(tp, 62041.61Skre unrelated_tracer_sees_terminaton_before_the_parent); 62051.67Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process); 62061.51Skamil 62071.51Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_child); 62081.66Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child); 62091.51Skamil 62101.51Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_parent); 62111.65Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent); 62121.51Skamil 62131.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 62141.51Skamil tracee_sees_its_original_parent_getppid); 62151.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 62161.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2); 62171.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 62181.51Skamil tracee_sees_its_original_parent_procfs_status); 62191.1Skamil 62201.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_empty); 62211.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_fork); 62221.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork); 62231.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done); 62241.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create); 62251.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit); 62261.1Skamil 62271.31Skamil ATF_TP_ADD_TC(tp, fork1); 62281.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork2); 62291.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork3); 62301.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork4); 62311.31Skamil ATF_TP_ADD_TC(tp, fork5); 62321.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork6); 62331.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork7); 62341.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, fork8); 62351.31Skamil 62361.31Skamil ATF_TP_ADD_TC(tp, vfork1); 62371.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork2); 62381.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork3); 62391.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork4); 62401.31Skamil ATF_TP_ADD_TC(tp, vfork5); 62411.31Skamil ATF_TP_ADD_TC_HAVE_PID(tp, vfork6); 62421.64Smartin// thes tests hang on SMP machines, disable them for now 62431.64Smartin// ATF_TP_ADD_TC_HAVE_PID(tp, vfork7); 62441.64Smartin// ATF_TP_ADD_TC_HAVE_PID(tp, vfork8); 62451.1Skamil 62461.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8); 62471.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16); 62481.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32); 62491.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64); 62501.54Skamil 62511.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8); 62521.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16); 62531.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32); 62541.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64); 62551.54Skamil 62561.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8); 62571.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16); 62581.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32); 62591.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64); 62601.54Skamil 62611.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8); 62621.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16); 62631.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32); 62641.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64); 62651.54Skamil 62661.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d); 62671.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i); 62681.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d); 62691.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i); 62701.54Skamil 62711.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text); 62721.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text); 62731.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text); 62741.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text); 62751.54Skamil 62761.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text); 62771.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text); 62781.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text); 62791.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text); 62801.54Skamil 62811.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text); 62821.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text); 62831.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text); 62841.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text); 62851.54Skamil 62861.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text); 62871.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text); 62881.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text); 62891.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text); 62901.54Skamil 62911.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text); 62921.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text); 62931.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text); 62941.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text); 62951.1Skamil 62961.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv); 62971.1Skamil 62981.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs1); 62991.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs2); 63001.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs3); 63011.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs4); 63021.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs5); 63031.72Skamil ATF_TP_ADD_TC_HAVE_GPREGS(tp, access_regs6); 63041.1Skamil 63051.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs1); 63061.72Skamil ATF_TP_ADD_TC_HAVE_FPREGS(tp, access_fpregs2); 63071.1Skamil 63081.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step1); 63091.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step2); 63101.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step3); 63111.1Skamil ATF_TP_ADD_TC_PT_STEP(tp, step4); 63121.1Skamil 63131.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep1); 63141.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep2); 63151.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep3); 63161.2Skamil ATF_TP_ADD_TC_PT_STEP(tp, setstep4); 63171.2Skamil 63181.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalmasked); 63191.95Skamil ATF_TP_ADD_TC_PT_STEP(tp, step_signalignored); 63201.95Skamil 63211.1Skamil ATF_TP_ADD_TC(tp, kill1); 63221.1Skamil ATF_TP_ADD_TC(tp, kill2); 63231.75Skamil ATF_TP_ADD_TC(tp, kill3); 63241.1Skamil 63251.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0); 63261.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1); 63271.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2); 63281.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3); 63291.77Skamil 63301.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0); 63311.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1); 63321.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2); 63331.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3); 63341.1Skamil 63351.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_unmodified); 63361.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_faked); 63371.79Skamil 63381.82Skamil ATF_TP_ADD_TC(tp, traceme_exec); 63391.1Skamil 63401.83Skamil ATF_TP_ADD_TC(tp, trace_thread1); 63411.83Skamil ATF_TP_ADD_TC(tp, trace_thread2); 63421.83Skamil ATF_TP_ADD_TC(tp, trace_thread3); 63431.83Skamil ATF_TP_ADD_TC(tp, trace_thread4); 63441.1Skamil 63451.84Skamil ATF_TP_ADD_TC(tp, signal_mask_unrelated); 63461.84Skamil 63471.1Skamil ATF_TP_ADD_TC(tp, signal5); 63481.1Skamil ATF_TP_ADD_TC_HAVE_PID(tp, signal6); 63491.1Skamil ATF_TP_ADD_TC_HAVE_PID(tp, signal7); 63501.1Skamil ATF_TP_ADD_TC(tp, signal8); 63511.1Skamil ATF_TP_ADD_TC(tp, signal9); 63521.1Skamil ATF_TP_ADD_TC(tp, signal10); 63531.1Skamil 63541.1Skamil ATF_TP_ADD_TC(tp, suspend1); 63551.1Skamil ATF_TP_ADD_TC(tp, suspend2); 63561.1Skamil 63571.1Skamil ATF_TP_ADD_TC(tp, resume1); 63581.1Skamil 63591.1Skamil ATF_TP_ADD_TC(tp, syscall1); 63601.1Skamil 63611.1Skamil ATF_TP_ADD_TC(tp, syscallemu1); 63621.1Skamil 63631.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64(); 63641.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_I386(); 63651.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_X86(); 63661.1Skamil 63671.1Skamil return atf_no_error(); 63681.1Skamil} 6369