t_ptrace_wait.c revision 1.180
11.180Skamil/* $NetBSD: t_ptrace_wait.c,v 1.180 2020/05/04 22:34:22 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.180Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.180 2020/05/04 22:34:22 kamil Exp $"); 311.143Skamil 321.143Skamil#define __LEGACY_PT_LWPINFO 331.1Skamil 341.1Skamil#include <sys/param.h> 351.1Skamil#include <sys/types.h> 361.130Smgorny#include <sys/exec_elf.h> 371.39Skamil#include <sys/mman.h> 381.1Skamil#include <sys/ptrace.h> 391.1Skamil#include <sys/resource.h> 401.1Skamil#include <sys/stat.h> 411.1Skamil#include <sys/syscall.h> 421.1Skamil#include <sys/sysctl.h> 431.129Smgorny#include <sys/uio.h> 441.1Skamil#include <sys/wait.h> 451.1Skamil#include <machine/reg.h> 461.132Skamil#include <assert.h> 471.1Skamil#include <elf.h> 481.1Skamil#include <err.h> 491.1Skamil#include <errno.h> 501.130Smgorny#include <fcntl.h> 511.1Skamil#include <lwp.h> 521.77Skamil#include <pthread.h> 531.1Skamil#include <sched.h> 541.1Skamil#include <signal.h> 551.124Skamil#include <spawn.h> 561.1Skamil#include <stdint.h> 571.1Skamil#include <stdio.h> 581.1Skamil#include <stdlib.h> 591.1Skamil#include <strings.h> 601.26Skamil#include <time.h> 611.1Skamil#include <unistd.h> 621.1Skamil 631.121Smgorny#if defined(__i386__) || defined(__x86_64__) 641.121Smgorny#include <cpuid.h> 651.121Smgorny#include <x86/cpu_extended_state.h> 661.129Smgorny#include <x86/specialreg.h> 671.121Smgorny#endif 681.121Smgorny 691.130Smgorny#include <libelf.h> 701.130Smgorny#include <gelf.h> 711.130Smgorny 721.1Skamil#include <atf-c.h> 731.1Skamil 741.165Skamil#ifdef ENABLE_TESTS 751.165Skamil 761.132Skamil/* Assumptions in the kernel code that must be kept. */ 771.171Skamil__CTASSERT(sizeof(((struct ptrace_state *)0)->pe_report_event) == 781.171Skamil sizeof(((siginfo_t *)0)->si_pe_report_event)); 791.171Skamil__CTASSERT(sizeof(((struct ptrace_state *)0)->pe_other_pid) == 801.171Skamil sizeof(((siginfo_t *)0)->si_pe_other_pid)); 811.171Skamil__CTASSERT(sizeof(((struct ptrace_state *)0)->pe_lwp) == 821.171Skamil sizeof(((siginfo_t *)0)->si_pe_lwp)); 831.171Skamil__CTASSERT(sizeof(((struct ptrace_state *)0)->pe_other_pid) == 841.171Skamil sizeof(((struct ptrace_state *)0)->pe_lwp)); 851.132Skamil 861.1Skamil#include "h_macros.h" 871.1Skamil 881.1Skamil#include "t_ptrace_wait.h" 891.1Skamil#include "msg.h" 901.1Skamil 911.13Schristos#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \ 921.13Schristos strerror(errno)) 931.18Schristos#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \ 941.18Schristos "%d(%s) != %d", res, strerror(res), exp) 951.13Schristos 961.152Skamilstatic int debug = 0; 971.13Schristos 981.13Schristos#define DPRINTF(a, ...) do \ 991.123Skamil if (debug) \ 1001.142Skamil printf("%s() %d.%d %s:%d " a, \ 1011.142Skamil __func__, getpid(), _lwp_self(), __FILE__, __LINE__, ##__VA_ARGS__); \ 1021.13Schristos while (/*CONSTCOND*/0) 1031.1Skamil 1041.34Skamil/// ---------------------------------------------------------------------------- 1051.34Skamil 1061.33Skamilstatic void 1071.33Skamiltraceme_raise(int sigval) 1081.1Skamil{ 1091.1Skamil const int exitval = 5; 1101.1Skamil pid_t child, wpid; 1111.1Skamil#if defined(TWAIT_HAVE_STATUS) 1121.1Skamil int status; 1131.1Skamil#endif 1141.1Skamil 1151.133Skamil ptrace_state_t state, zero_state; 1161.133Skamil const int slen = sizeof(state); 1171.45Skamil struct ptrace_siginfo info; 1181.133Skamil memset(&zero_state, 0, sizeof(zero_state)); 1191.45Skamil memset(&info, 0, sizeof(info)); 1201.45Skamil 1211.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 1221.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 1231.1Skamil if (child == 0) { 1241.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1251.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1261.1Skamil 1271.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1281.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 1291.1Skamil 1301.36Skamil switch (sigval) { 1311.36Skamil case SIGKILL: 1321.36Skamil /* NOTREACHED */ 1331.36Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 1341.70Smrg __unreachable(); 1351.36Skamil default: 1361.36Skamil DPRINTF("Before exiting of the child process\n"); 1371.36Skamil _exit(exitval); 1381.36Skamil } 1391.1Skamil } 1401.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1411.1Skamil 1421.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1431.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1441.1Skamil 1451.36Skamil switch (sigval) { 1461.36Skamil case SIGKILL: 1471.36Skamil validate_status_signaled(status, sigval, 0); 1481.133Skamil SYSCALL_REQUIRE( 1491.133Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) == -1); 1501.133Skamil 1511.36Skamil break; 1521.36Skamil default: 1531.36Skamil validate_status_stopped(status, sigval); 1541.1Skamil 1551.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 1561.61Skre "child\n"); 1571.45Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 1581.61Skre sizeof(info)) != -1); 1591.45Skamil 1601.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1611.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 1621.61Skre "si_errno=%#x\n", 1631.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1641.61Skre info.psi_siginfo.si_errno); 1651.45Skamil 1661.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 1671.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 1681.45Skamil 1691.133Skamil DPRINTF("Assert that PT_GET_PROCESS_STATE returns non-error"); 1701.133Skamil SYSCALL_REQUIRE( 1711.133Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 1721.133Skamil ATF_REQUIRE(memcmp(&state, &zero_state, slen) == 0); 1731.133Skamil 1741.36Skamil DPRINTF("Before resuming the child process where it left off " 1751.36Skamil "and without signal to be sent\n"); 1761.36Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1771.1Skamil 1781.36Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1791.36Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 1801.61Skre child); 1811.36Skamil break; 1821.36Skamil } 1831.1Skamil 1841.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1851.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 1861.1Skamil} 1871.1Skamil 1881.61Skre#define TRACEME_RAISE(test, sig) \ 1891.61SkreATF_TC(test); \ 1901.61SkreATF_TC_HEAD(test, tc) \ 1911.61Skre{ \ 1921.61Skre atf_tc_set_md_var(tc, "descr", \ 1931.61Skre "Verify " #sig " followed by _exit(2) in a child"); \ 1941.61Skre} \ 1951.61Skre \ 1961.61SkreATF_TC_BODY(test, tc) \ 1971.61Skre{ \ 1981.61Skre \ 1991.61Skre traceme_raise(sig); \ 2001.33Skamil} 2011.33Skamil 2021.36SkamilTRACEME_RAISE(traceme_raise1, SIGKILL) /* non-maskable */ 2031.33SkamilTRACEME_RAISE(traceme_raise2, SIGSTOP) /* non-maskable */ 2041.33SkamilTRACEME_RAISE(traceme_raise3, SIGABRT) /* regular abort trap */ 2051.33SkamilTRACEME_RAISE(traceme_raise4, SIGHUP) /* hangup */ 2061.33SkamilTRACEME_RAISE(traceme_raise5, SIGCONT) /* continued? */ 2071.85SkamilTRACEME_RAISE(traceme_raise6, SIGTRAP) /* crash signal */ 2081.85SkamilTRACEME_RAISE(traceme_raise7, SIGBUS) /* crash signal */ 2091.85SkamilTRACEME_RAISE(traceme_raise8, SIGILL) /* crash signal */ 2101.85SkamilTRACEME_RAISE(traceme_raise9, SIGFPE) /* crash signal */ 2111.85SkamilTRACEME_RAISE(traceme_raise10, SIGSEGV) /* crash signal */ 2121.33Skamil 2131.34Skamil/// ---------------------------------------------------------------------------- 2141.1Skamil 2151.1Skamilstatic void 2161.87Skamiltraceme_raisesignal_ignored(int sigignored) 2171.87Skamil{ 2181.87Skamil const int exitval = 5; 2191.87Skamil const int sigval = SIGSTOP; 2201.87Skamil pid_t child, wpid; 2211.87Skamil struct sigaction sa; 2221.87Skamil#if defined(TWAIT_HAVE_STATUS) 2231.87Skamil int status; 2241.87Skamil#endif 2251.87Skamil struct ptrace_siginfo info; 2261.87Skamil 2271.87Skamil memset(&info, 0, sizeof(info)); 2281.87Skamil 2291.87Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 2301.87Skamil SYSCALL_REQUIRE((child = fork()) != -1); 2311.87Skamil if (child == 0) { 2321.87Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2331.87Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2341.87Skamil 2351.87Skamil memset(&sa, 0, sizeof(sa)); 2361.87Skamil sa.sa_handler = SIG_IGN; 2371.87Skamil sigemptyset(&sa.sa_mask); 2381.87Skamil FORKEE_ASSERT(sigaction(sigignored, &sa, NULL) != -1); 2391.87Skamil 2401.87Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 2411.87Skamil FORKEE_ASSERT(raise(sigval) == 0); 2421.87Skamil 2431.87Skamil DPRINTF("Before raising %s from child\n", 2441.87Skamil strsignal(sigignored)); 2451.87Skamil FORKEE_ASSERT(raise(sigignored) == 0); 2461.87Skamil 2471.87Skamil DPRINTF("Before exiting of the child process\n"); 2481.87Skamil _exit(exitval); 2491.87Skamil } 2501.87Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2511.87Skamil 2521.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2531.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2541.87Skamil 2551.87Skamil validate_status_stopped(status, sigval); 2561.87Skamil 2571.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2581.87Skamil SYSCALL_REQUIRE( 2591.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2601.87Skamil 2611.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2621.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2631.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2641.87Skamil info.psi_siginfo.si_errno); 2651.87Skamil 2661.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 2671.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2681.87Skamil 2691.87Skamil DPRINTF("Before resuming the child process where it left off and " 2701.87Skamil "without signal to be sent\n"); 2711.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2721.87Skamil 2731.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2741.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2751.87Skamil 2761.87Skamil validate_status_stopped(status, sigignored); 2771.87Skamil 2781.87Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2791.87Skamil SYSCALL_REQUIRE( 2801.87Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2811.87Skamil 2821.87Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2831.87Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2841.87Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2851.87Skamil info.psi_siginfo.si_errno); 2861.87Skamil 2871.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigignored); 2881.87Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2891.87Skamil 2901.87Skamil DPRINTF("Before resuming the child process where it left off and " 2911.87Skamil "without signal to be sent\n"); 2921.87Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2931.87Skamil 2941.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2951.87Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2961.87Skamil 2971.87Skamil validate_status_exited(status, exitval); 2981.87Skamil 2991.87Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3001.87Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 3011.87Skamil} 3021.87Skamil 3031.87Skamil#define TRACEME_RAISESIGNAL_IGNORED(test, sig) \ 3041.87SkamilATF_TC(test); \ 3051.87SkamilATF_TC_HEAD(test, tc) \ 3061.87Skamil{ \ 3071.87Skamil atf_tc_set_md_var(tc, "descr", \ 3081.87Skamil "Verify that ignoring (with SIG_IGN) " #sig " in tracee " \ 3091.87Skamil "does not stop tracer from catching this raised signal"); \ 3101.87Skamil} \ 3111.87Skamil \ 3121.87SkamilATF_TC_BODY(test, tc) \ 3131.87Skamil{ \ 3141.87Skamil \ 3151.87Skamil traceme_raisesignal_ignored(sig); \ 3161.87Skamil} 3171.87Skamil 3181.87Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 3191.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored1, SIGABRT) /* abort */ 3201.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored2, SIGHUP) /* hangup */ 3211.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored3, SIGCONT) /* cont. */ 3221.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored4, SIGTRAP) /* crash */ 3231.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored5, SIGBUS) /* crash */ 3241.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored6, SIGILL) /* crash */ 3251.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored7, SIGFPE) /* crash */ 3261.87SkamilTRACEME_RAISESIGNAL_IGNORED(traceme_raisesignal_ignored8, SIGSEGV) /* crash */ 3271.87Skamil 3281.87Skamil/// ---------------------------------------------------------------------------- 3291.87Skamil 3301.87Skamilstatic void 3311.86Skamiltraceme_raisesignal_masked(int sigmasked) 3321.86Skamil{ 3331.86Skamil const int exitval = 5; 3341.86Skamil const int sigval = SIGSTOP; 3351.86Skamil pid_t child, wpid; 3361.86Skamil#if defined(TWAIT_HAVE_STATUS) 3371.86Skamil int status; 3381.86Skamil#endif 3391.86Skamil sigset_t intmask; 3401.86Skamil struct ptrace_siginfo info; 3411.86Skamil 3421.86Skamil memset(&info, 0, sizeof(info)); 3431.86Skamil 3441.86Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 3451.86Skamil SYSCALL_REQUIRE((child = fork()) != -1); 3461.86Skamil if (child == 0) { 3471.86Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 3481.86Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 3491.86Skamil 3501.86Skamil sigemptyset(&intmask); 3511.86Skamil sigaddset(&intmask, sigmasked); 3521.86Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 3531.86Skamil 3541.86Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 3551.86Skamil FORKEE_ASSERT(raise(sigval) == 0); 3561.86Skamil 3571.86Skamil DPRINTF("Before raising %s breakpoint from child\n", 3581.86Skamil strsignal(sigmasked)); 3591.86Skamil FORKEE_ASSERT(raise(sigmasked) == 0); 3601.86Skamil 3611.86Skamil DPRINTF("Before exiting of the child process\n"); 3621.86Skamil _exit(exitval); 3631.86Skamil } 3641.86Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 3651.86Skamil 3661.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3671.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3681.86Skamil 3691.86Skamil validate_status_stopped(status, sigval); 3701.86Skamil 3711.86Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 3721.86Skamil SYSCALL_REQUIRE( 3731.86Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 3741.86Skamil 3751.86Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 3761.86Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 3771.86Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 3781.86Skamil info.psi_siginfo.si_errno); 3791.86Skamil 3801.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 3811.86Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 3821.86Skamil 3831.86Skamil DPRINTF("Before resuming the child process where it left off and " 3841.86Skamil "without signal to be sent\n"); 3851.86Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 3861.86Skamil 3871.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3881.86Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 3891.86Skamil 3901.86Skamil validate_status_exited(status, exitval); 3911.86Skamil 3921.86Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 3931.86Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 3941.86Skamil} 3951.86Skamil 3961.86Skamil#define TRACEME_RAISESIGNAL_MASKED(test, sig) \ 3971.86SkamilATF_TC(test); \ 3981.86SkamilATF_TC_HEAD(test, tc) \ 3991.86Skamil{ \ 4001.86Skamil atf_tc_set_md_var(tc, "descr", \ 4011.86Skamil "Verify that masking (with SIG_BLOCK) " #sig " in tracee " \ 4021.86Skamil "stops tracer from catching this raised signal"); \ 4031.86Skamil} \ 4041.86Skamil \ 4051.86SkamilATF_TC_BODY(test, tc) \ 4061.86Skamil{ \ 4071.86Skamil \ 4081.86Skamil traceme_raisesignal_masked(sig); \ 4091.86Skamil} 4101.86Skamil 4111.86Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 4121.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked1, SIGABRT) /* abort trap */ 4131.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked2, SIGHUP) /* hangup */ 4141.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked3, SIGCONT) /* continued? */ 4151.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked4, SIGTRAP) /* crash sig. */ 4161.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked5, SIGBUS) /* crash sig. */ 4171.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked6, SIGILL) /* crash sig. */ 4181.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked7, SIGFPE) /* crash sig. */ 4191.86SkamilTRACEME_RAISESIGNAL_MASKED(traceme_raisesignal_masked8, SIGSEGV) /* crash sig. */ 4201.86Skamil 4211.86Skamil/// ---------------------------------------------------------------------------- 4221.86Skamil 4231.86Skamilstatic void 4241.59Skamiltraceme_crash(int sig) 4251.59Skamil{ 4261.59Skamil pid_t child, wpid; 4271.59Skamil#if defined(TWAIT_HAVE_STATUS) 4281.59Skamil int status; 4291.59Skamil#endif 4301.59Skamil struct ptrace_siginfo info; 4311.61Skre 4321.71Skamil#ifndef PTRACE_ILLEGAL_ASM 4331.71Skamil if (sig == SIGILL) 4341.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 4351.71Skamil#endif 4361.71Skamil 4371.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 4381.114Skamil atf_tc_skip("FP exceptions are not supported"); 4391.114Skamil 4401.59Skamil memset(&info, 0, sizeof(info)); 4411.59Skamil 4421.59Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 4431.59Skamil SYSCALL_REQUIRE((child = fork()) != -1); 4441.59Skamil if (child == 0) { 4451.59Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 4461.59Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 4471.59Skamil 4481.59Skamil DPRINTF("Before executing a trap\n"); 4491.59Skamil switch (sig) { 4501.59Skamil case SIGTRAP: 4511.59Skamil trigger_trap(); 4521.59Skamil break; 4531.59Skamil case SIGSEGV: 4541.59Skamil trigger_segv(); 4551.59Skamil break; 4561.59Skamil case SIGILL: 4571.59Skamil trigger_ill(); 4581.59Skamil break; 4591.59Skamil case SIGFPE: 4601.59Skamil trigger_fpe(); 4611.59Skamil break; 4621.59Skamil case SIGBUS: 4631.59Skamil trigger_bus(); 4641.59Skamil break; 4651.59Skamil default: 4661.59Skamil /* NOTREACHED */ 4671.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4681.59Skamil } 4691.59Skamil 4701.59Skamil /* NOTREACHED */ 4711.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 4721.59Skamil } 4731.59Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 4741.59Skamil 4751.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4761.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4771.59Skamil 4781.59Skamil validate_status_stopped(status, sig); 4791.59Skamil 4801.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 4811.61Skre SYSCALL_REQUIRE( 4821.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 4831.59Skamil 4841.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 4851.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 4861.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 4871.61Skre info.psi_siginfo.si_errno); 4881.59Skamil 4891.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 4901.59Skamil switch (sig) { 4911.59Skamil case SIGTRAP: 4921.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 4931.59Skamil break; 4941.59Skamil case SIGSEGV: 4951.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 4961.59Skamil break; 4971.71Skamil case SIGILL: 4981.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 4991.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 5001.71Skamil break; 5011.59Skamil case SIGFPE: 5021.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 5031.59Skamil break; 5041.59Skamil case SIGBUS: 5051.59Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 5061.59Skamil break; 5071.59Skamil } 5081.59Skamil 5091.59Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 5101.59Skamil 5111.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5121.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 5131.59Skamil 5141.59Skamil validate_status_signaled(status, SIGKILL, 0); 5151.59Skamil 5161.59Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5171.59Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 5181.59Skamil} 5191.59Skamil 5201.61Skre#define TRACEME_CRASH(test, sig) \ 5211.61SkreATF_TC(test); \ 5221.61SkreATF_TC_HEAD(test, tc) \ 5231.61Skre{ \ 5241.61Skre atf_tc_set_md_var(tc, "descr", \ 5251.61Skre "Verify crash signal " #sig " in a child after PT_TRACE_ME"); \ 5261.61Skre} \ 5271.61Skre \ 5281.61SkreATF_TC_BODY(test, tc) \ 5291.61Skre{ \ 5301.61Skre \ 5311.61Skre traceme_crash(sig); \ 5321.59Skamil} 5331.59Skamil 5341.59SkamilTRACEME_CRASH(traceme_crash_trap, SIGTRAP) 5351.59SkamilTRACEME_CRASH(traceme_crash_segv, SIGSEGV) 5361.71SkamilTRACEME_CRASH(traceme_crash_ill, SIGILL) 5371.59SkamilTRACEME_CRASH(traceme_crash_fpe, SIGFPE) 5381.59SkamilTRACEME_CRASH(traceme_crash_bus, SIGBUS) 5391.59Skamil 5401.59Skamil/// ---------------------------------------------------------------------------- 5411.59Skamil 5421.59Skamilstatic void 5431.88Skamiltraceme_signalmasked_crash(int sig) 5441.88Skamil{ 5451.89Skamil const int sigval = SIGSTOP; 5461.88Skamil pid_t child, wpid; 5471.88Skamil#if defined(TWAIT_HAVE_STATUS) 5481.88Skamil int status; 5491.88Skamil#endif 5501.88Skamil struct ptrace_siginfo info; 5511.88Skamil sigset_t intmask; 5521.89Skamil struct kinfo_proc2 kp; 5531.89Skamil size_t len = sizeof(kp); 5541.89Skamil 5551.89Skamil int name[6]; 5561.89Skamil const size_t namelen = __arraycount(name); 5571.89Skamil ki_sigset_t kp_sigmask; 5581.88Skamil 5591.88Skamil#ifndef PTRACE_ILLEGAL_ASM 5601.88Skamil if (sig == SIGILL) 5611.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 5621.88Skamil#endif 5631.88Skamil 5641.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 5651.114Skamil atf_tc_skip("FP exceptions are not supported"); 5661.114Skamil 5671.88Skamil memset(&info, 0, sizeof(info)); 5681.88Skamil 5691.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 5701.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 5711.88Skamil if (child == 0) { 5721.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 5731.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 5741.88Skamil 5751.88Skamil sigemptyset(&intmask); 5761.88Skamil sigaddset(&intmask, sig); 5771.88Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 5781.88Skamil 5791.89Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 5801.89Skamil FORKEE_ASSERT(raise(sigval) == 0); 5811.89Skamil 5821.88Skamil DPRINTF("Before executing a trap\n"); 5831.88Skamil switch (sig) { 5841.88Skamil case SIGTRAP: 5851.88Skamil trigger_trap(); 5861.88Skamil break; 5871.88Skamil case SIGSEGV: 5881.88Skamil trigger_segv(); 5891.88Skamil break; 5901.88Skamil case SIGILL: 5911.88Skamil trigger_ill(); 5921.88Skamil break; 5931.88Skamil case SIGFPE: 5941.88Skamil trigger_fpe(); 5951.88Skamil break; 5961.88Skamil case SIGBUS: 5971.88Skamil trigger_bus(); 5981.88Skamil break; 5991.88Skamil default: 6001.88Skamil /* NOTREACHED */ 6011.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 6021.88Skamil } 6031.88Skamil 6041.88Skamil /* NOTREACHED */ 6051.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 6061.88Skamil } 6071.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 6081.88Skamil 6091.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6101.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6111.88Skamil 6121.89Skamil validate_status_stopped(status, sigval); 6131.89Skamil 6141.89Skamil name[0] = CTL_KERN, 6151.89Skamil name[1] = KERN_PROC2, 6161.89Skamil name[2] = KERN_PROC_PID; 6171.89Skamil name[3] = child; 6181.89Skamil name[4] = sizeof(kp); 6191.89Skamil name[5] = 1; 6201.89Skamil 6211.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6221.89Skamil 6231.89Skamil kp_sigmask = kp.p_sigmask; 6241.89Skamil 6251.89Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 6261.89Skamil SYSCALL_REQUIRE( 6271.89Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6281.89Skamil 6291.89Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6301.89Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6311.89Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6321.89Skamil info.psi_siginfo.si_errno); 6331.89Skamil 6341.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 6351.89Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 6361.89Skamil 6371.89Skamil DPRINTF("Before resuming the child process where it left off and " 6381.89Skamil "without signal to be sent\n"); 6391.89Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 6401.89Skamil 6411.89Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6421.89Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6431.89Skamil 6441.88Skamil validate_status_stopped(status, sig); 6451.88Skamil 6461.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 6471.88Skamil SYSCALL_REQUIRE( 6481.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 6491.88Skamil 6501.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 6511.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 6521.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 6531.88Skamil info.psi_siginfo.si_errno); 6541.88Skamil 6551.89Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 6561.89Skamil 6571.89Skamil DPRINTF("kp_sigmask=" 6581.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6591.89Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], kp_sigmask.__bits[2], 6601.89Skamil kp_sigmask.__bits[3]); 6611.89Skamil 6621.89Skamil DPRINTF("kp.p_sigmask=" 6631.89Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 6641.89Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 6651.89Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 6661.89Skamil 6671.89Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, sizeof(kp_sigmask))); 6681.89Skamil 6691.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 6701.88Skamil switch (sig) { 6711.88Skamil case SIGTRAP: 6721.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 6731.88Skamil break; 6741.88Skamil case SIGSEGV: 6751.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 6761.88Skamil break; 6771.88Skamil case SIGILL: 6781.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 6791.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 6801.88Skamil break; 6811.88Skamil case SIGFPE: 6821.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 6831.88Skamil break; 6841.88Skamil case SIGBUS: 6851.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 6861.88Skamil break; 6871.88Skamil } 6881.88Skamil 6891.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 6901.88Skamil 6911.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6921.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 6931.88Skamil 6941.88Skamil validate_status_signaled(status, SIGKILL, 0); 6951.88Skamil 6961.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 6971.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 6981.88Skamil} 6991.88Skamil 7001.88Skamil#define TRACEME_SIGNALMASKED_CRASH(test, sig) \ 7011.88SkamilATF_TC(test); \ 7021.88SkamilATF_TC_HEAD(test, tc) \ 7031.88Skamil{ \ 7041.88Skamil atf_tc_set_md_var(tc, "descr", \ 7051.88Skamil "Verify masked crash signal " #sig " in a child after " \ 7061.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 7071.88Skamil} \ 7081.88Skamil \ 7091.88SkamilATF_TC_BODY(test, tc) \ 7101.88Skamil{ \ 7111.88Skamil \ 7121.88Skamil traceme_signalmasked_crash(sig); \ 7131.88Skamil} 7141.88Skamil 7151.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_trap, SIGTRAP) 7161.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_segv, SIGSEGV) 7171.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_ill, SIGILL) 7181.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_fpe, SIGFPE) 7191.88SkamilTRACEME_SIGNALMASKED_CRASH(traceme_signalmasked_crash_bus, SIGBUS) 7201.88Skamil 7211.88Skamil/// ---------------------------------------------------------------------------- 7221.88Skamil 7231.88Skamilstatic void 7241.88Skamiltraceme_signalignored_crash(int sig) 7251.88Skamil{ 7261.90Skamil const int sigval = SIGSTOP; 7271.88Skamil pid_t child, wpid; 7281.88Skamil#if defined(TWAIT_HAVE_STATUS) 7291.88Skamil int status; 7301.88Skamil#endif 7311.88Skamil struct sigaction sa; 7321.88Skamil struct ptrace_siginfo info; 7331.90Skamil struct kinfo_proc2 kp; 7341.90Skamil size_t len = sizeof(kp); 7351.90Skamil 7361.90Skamil int name[6]; 7371.90Skamil const size_t namelen = __arraycount(name); 7381.90Skamil ki_sigset_t kp_sigignore; 7391.88Skamil 7401.88Skamil#ifndef PTRACE_ILLEGAL_ASM 7411.88Skamil if (sig == SIGILL) 7421.88Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 7431.88Skamil#endif 7441.88Skamil 7451.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 7461.114Skamil atf_tc_skip("FP exceptions are not supported"); 7471.114Skamil 7481.88Skamil memset(&info, 0, sizeof(info)); 7491.88Skamil 7501.88Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 7511.88Skamil SYSCALL_REQUIRE((child = fork()) != -1); 7521.88Skamil if (child == 0) { 7531.88Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 7541.88Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 7551.88Skamil 7561.88Skamil memset(&sa, 0, sizeof(sa)); 7571.88Skamil sa.sa_handler = SIG_IGN; 7581.88Skamil sigemptyset(&sa.sa_mask); 7591.88Skamil 7601.88Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 7611.88Skamil 7621.90Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 7631.90Skamil FORKEE_ASSERT(raise(sigval) == 0); 7641.90Skamil 7651.88Skamil DPRINTF("Before executing a trap\n"); 7661.88Skamil switch (sig) { 7671.88Skamil case SIGTRAP: 7681.88Skamil trigger_trap(); 7691.88Skamil break; 7701.88Skamil case SIGSEGV: 7711.88Skamil trigger_segv(); 7721.88Skamil break; 7731.88Skamil case SIGILL: 7741.88Skamil trigger_ill(); 7751.88Skamil break; 7761.88Skamil case SIGFPE: 7771.88Skamil trigger_fpe(); 7781.88Skamil break; 7791.88Skamil case SIGBUS: 7801.88Skamil trigger_bus(); 7811.88Skamil break; 7821.88Skamil default: 7831.88Skamil /* NOTREACHED */ 7841.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7851.88Skamil } 7861.88Skamil 7871.88Skamil /* NOTREACHED */ 7881.88Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 7891.88Skamil } 7901.88Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 7911.88Skamil 7921.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7931.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 7941.88Skamil 7951.90Skamil validate_status_stopped(status, sigval); 7961.90Skamil 7971.90Skamil name[0] = CTL_KERN, 7981.90Skamil name[1] = KERN_PROC2, 7991.90Skamil name[2] = KERN_PROC_PID; 8001.90Skamil name[3] = child; 8011.90Skamil name[4] = sizeof(kp); 8021.90Skamil name[5] = 1; 8031.90Skamil 8041.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8051.90Skamil 8061.90Skamil kp_sigignore = kp.p_sigignore; 8071.90Skamil 8081.90Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 8091.90Skamil SYSCALL_REQUIRE( 8101.90Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8111.90Skamil 8121.90Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8131.90Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8141.90Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8151.90Skamil info.psi_siginfo.si_errno); 8161.90Skamil 8171.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 8181.90Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 8191.90Skamil 8201.90Skamil DPRINTF("Before resuming the child process where it left off and " 8211.90Skamil "without signal to be sent\n"); 8221.90Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 8231.90Skamil 8241.90Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8251.90Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8261.90Skamil 8271.88Skamil validate_status_stopped(status, sig); 8281.88Skamil 8291.88Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 8301.88Skamil SYSCALL_REQUIRE( 8311.88Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 8321.88Skamil 8331.88Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 8341.88Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 8351.88Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 8361.88Skamil info.psi_siginfo.si_errno); 8371.88Skamil 8381.90Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8391.90Skamil 8401.90Skamil DPRINTF("kp_sigignore=" 8411.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8421.90Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 8431.90Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 8441.90Skamil 8451.90Skamil DPRINTF("kp.p_sigignore=" 8461.90Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 8471.90Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 8481.90Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 8491.90Skamil 8501.90Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, sizeof(kp_sigignore))); 8511.90Skamil 8521.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sig); 8531.88Skamil switch (sig) { 8541.88Skamil case SIGTRAP: 8551.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 8561.88Skamil break; 8571.88Skamil case SIGSEGV: 8581.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 8591.88Skamil break; 8601.88Skamil case SIGILL: 8611.113Skamil ATF_REQUIRE(info.psi_siginfo.si_code >= ILL_ILLOPC && 8621.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 8631.88Skamil break; 8641.88Skamil case SIGFPE: 8651.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 8661.88Skamil break; 8671.88Skamil case SIGBUS: 8681.88Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 8691.88Skamil break; 8701.88Skamil } 8711.88Skamil 8721.88Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 8731.88Skamil 8741.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8751.88Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 8761.88Skamil 8771.88Skamil validate_status_signaled(status, SIGKILL, 0); 8781.88Skamil 8791.88Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 8801.88Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 8811.88Skamil} 8821.88Skamil 8831.88Skamil#define TRACEME_SIGNALIGNORED_CRASH(test, sig) \ 8841.88SkamilATF_TC(test); \ 8851.88SkamilATF_TC_HEAD(test, tc) \ 8861.88Skamil{ \ 8871.88Skamil atf_tc_set_md_var(tc, "descr", \ 8881.88Skamil "Verify ignored crash signal " #sig " in a child after " \ 8891.88Skamil "PT_TRACE_ME is delivered to its tracer"); \ 8901.88Skamil} \ 8911.88Skamil \ 8921.88SkamilATF_TC_BODY(test, tc) \ 8931.88Skamil{ \ 8941.88Skamil \ 8951.88Skamil traceme_signalignored_crash(sig); \ 8961.88Skamil} 8971.88Skamil 8981.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_trap, SIGTRAP) 8991.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_segv, SIGSEGV) 9001.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_ill, SIGILL) 9011.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_fpe, SIGFPE) 9021.88SkamilTRACEME_SIGNALIGNORED_CRASH(traceme_signalignored_crash_bus, SIGBUS) 9031.88Skamil 9041.88Skamil/// ---------------------------------------------------------------------------- 9051.88Skamil 9061.88Skamilstatic void 9071.50Skamiltraceme_sendsignal_handle(int sigsent, void (*sah)(int a), int *traceme_caught) 9081.1Skamil{ 9091.1Skamil const int exitval = 5; 9101.34Skamil const int sigval = SIGSTOP; 9111.1Skamil pid_t child, wpid; 9121.1Skamil struct sigaction sa; 9131.1Skamil#if defined(TWAIT_HAVE_STATUS) 9141.1Skamil int status; 9151.1Skamil#endif 9161.61Skre struct ptrace_siginfo info; 9171.1Skamil 9181.45Skamil memset(&info, 0, sizeof(info)); 9191.45Skamil 9201.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 9211.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 9221.1Skamil if (child == 0) { 9231.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 9241.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 9251.1Skamil 9261.34Skamil sa.sa_handler = sah; 9271.1Skamil sa.sa_flags = SA_SIGINFO; 9281.1Skamil sigemptyset(&sa.sa_mask); 9291.1Skamil 9301.1Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 9311.1Skamil 9321.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 9331.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 9341.1Skamil 9351.34Skamil FORKEE_ASSERT_EQ(*traceme_caught, 1); 9361.1Skamil 9371.13Schristos DPRINTF("Before exiting of the child process\n"); 9381.1Skamil _exit(exitval); 9391.1Skamil } 9401.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 9411.1Skamil 9421.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9431.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9441.1Skamil 9451.1Skamil validate_status_stopped(status, sigval); 9461.1Skamil 9471.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 9481.61Skre SYSCALL_REQUIRE( 9491.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 9501.45Skamil 9511.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 9521.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 9531.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 9541.45Skamil info.psi_siginfo.si_errno); 9551.45Skamil 9561.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 9571.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 9581.45Skamil 9591.13Schristos DPRINTF("Before resuming the child process where it left off and with " 9601.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 9611.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 9621.1Skamil 9631.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 9641.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 9651.1Skamil 9661.1Skamil validate_status_exited(status, exitval); 9671.1Skamil 9681.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 9691.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 9701.1Skamil} 9711.1Skamil 9721.61Skre#define TRACEME_SENDSIGNAL_HANDLE(test, sig) \ 9731.61SkreATF_TC(test); \ 9741.61SkreATF_TC_HEAD(test, tc) \ 9751.61Skre{ \ 9761.61Skre atf_tc_set_md_var(tc, "descr", \ 9771.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 9781.61Skre "handled correctly and caught by a signal handler"); \ 9791.61Skre} \ 9801.61Skre \ 9811.61Skrestatic int test##_caught = 0; \ 9821.61Skre \ 9831.61Skrestatic void \ 9841.61Skretest##_sighandler(int arg) \ 9851.61Skre{ \ 9861.61Skre FORKEE_ASSERT_EQ(arg, sig); \ 9871.61Skre \ 9881.61Skre ++ test##_caught; \ 9891.61Skre} \ 9901.61Skre \ 9911.61SkreATF_TC_BODY(test, tc) \ 9921.61Skre{ \ 9931.61Skre \ 9941.61Skre traceme_sendsignal_handle(sig, test##_sighandler, & test##_caught); \ 9951.34Skamil} 9961.34Skamil 9971.34Skamil// A signal handler for SIGKILL and SIGSTOP cannot be registered. 9981.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle1, SIGABRT) /* abort trap */ 9991.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle2, SIGHUP) /* hangup */ 10001.50SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle3, SIGCONT) /* continued? */ 10011.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle4, SIGTRAP) /* crash sig. */ 10021.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle5, SIGBUS) /* crash sig. */ 10031.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle6, SIGILL) /* crash sig. */ 10041.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle7, SIGFPE) /* crash sig. */ 10051.85SkamilTRACEME_SENDSIGNAL_HANDLE(traceme_sendsignal_handle8, SIGSEGV) /* crash sig. */ 10061.34Skamil 10071.34Skamil/// ---------------------------------------------------------------------------- 10081.34Skamil 10091.35Skamilstatic void 10101.50Skamiltraceme_sendsignal_masked(int sigsent) 10111.50Skamil{ 10121.50Skamil const int exitval = 5; 10131.50Skamil const int sigval = SIGSTOP; 10141.50Skamil pid_t child, wpid; 10151.50Skamil sigset_t set; 10161.50Skamil#if defined(TWAIT_HAVE_STATUS) 10171.50Skamil int status; 10181.50Skamil#endif 10191.61Skre struct ptrace_siginfo info; 10201.50Skamil 10211.50Skamil memset(&info, 0, sizeof(info)); 10221.50Skamil 10231.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 10241.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 10251.50Skamil if (child == 0) { 10261.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 10271.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 10281.50Skamil 10291.50Skamil sigemptyset(&set); 10301.50Skamil sigaddset(&set, sigsent); 10311.50Skamil FORKEE_ASSERT(sigprocmask(SIG_BLOCK, &set, NULL) != -1); 10321.50Skamil 10331.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 10341.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 10351.50Skamil 10361.50Skamil _exit(exitval); 10371.50Skamil } 10381.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 10391.50Skamil 10401.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10411.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10421.50Skamil 10431.50Skamil validate_status_stopped(status, sigval); 10441.50Skamil 10451.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 10461.61Skre SYSCALL_REQUIRE( 10471.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 10481.50Skamil 10491.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 10501.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 10511.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 10521.50Skamil info.psi_siginfo.si_errno); 10531.50Skamil 10541.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 10551.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 10561.50Skamil 10571.50Skamil DPRINTF("Before resuming the child process where it left off and with " 10581.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 10591.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 10601.50Skamil 10611.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10621.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10631.50Skamil 10641.50Skamil validate_status_exited(status, exitval); 10651.50Skamil 10661.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 10671.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 10681.50Skamil} 10691.50Skamil 10701.61Skre#define TRACEME_SENDSIGNAL_MASKED(test, sig) \ 10711.61SkreATF_TC(test); \ 10721.61SkreATF_TC_HEAD(test, tc) \ 10731.61Skre{ \ 10741.61Skre atf_tc_set_md_var(tc, "descr", \ 10751.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 10761.61Skre "handled correctly and the signal is masked by SIG_BLOCK"); \ 10771.61Skre} \ 10781.61Skre \ 10791.61SkreATF_TC_BODY(test, tc) \ 10801.61Skre{ \ 10811.61Skre \ 10821.61Skre traceme_sendsignal_masked(sig); \ 10831.50Skamil} 10841.50Skamil 10851.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be masked. 10861.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked1, SIGABRT) /* abort trap */ 10871.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked2, SIGHUP) /* hangup */ 10881.50SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked3, SIGCONT) /* continued? */ 10891.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked4, SIGTRAP) /* crash sig. */ 10901.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked5, SIGBUS) /* crash sig. */ 10911.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked6, SIGILL) /* crash sig. */ 10921.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked7, SIGFPE) /* crash sig. */ 10931.85SkamilTRACEME_SENDSIGNAL_MASKED(traceme_sendsignal_masked8, SIGSEGV) /* crash sig. */ 10941.50Skamil 10951.50Skamil/// ---------------------------------------------------------------------------- 10961.50Skamil 10971.50Skamilstatic void 10981.50Skamiltraceme_sendsignal_ignored(int sigsent) 10991.50Skamil{ 11001.50Skamil const int exitval = 5; 11011.50Skamil const int sigval = SIGSTOP; 11021.50Skamil pid_t child, wpid; 11031.50Skamil struct sigaction sa; 11041.50Skamil#if defined(TWAIT_HAVE_STATUS) 11051.50Skamil int status; 11061.50Skamil#endif 11071.61Skre struct ptrace_siginfo info; 11081.50Skamil 11091.50Skamil memset(&info, 0, sizeof(info)); 11101.50Skamil 11111.50Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 11121.50Skamil SYSCALL_REQUIRE((child = fork()) != -1); 11131.50Skamil if (child == 0) { 11141.50Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 11151.61Skre 11161.50Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 11171.50Skamil 11181.50Skamil memset(&sa, 0, sizeof(sa)); 11191.50Skamil sa.sa_handler = SIG_IGN; 11201.50Skamil sigemptyset(&sa.sa_mask); 11211.50Skamil FORKEE_ASSERT(sigaction(sigsent, &sa, NULL) != -1); 11221.50Skamil 11231.50Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 11241.50Skamil FORKEE_ASSERT(raise(sigval) == 0); 11251.50Skamil 11261.50Skamil _exit(exitval); 11271.50Skamil } 11281.50Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 11291.50Skamil 11301.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11311.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11321.50Skamil 11331.50Skamil validate_status_stopped(status, sigval); 11341.50Skamil 11351.50Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 11361.61Skre SYSCALL_REQUIRE( 11371.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 11381.50Skamil 11391.50Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 11401.50Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 11411.50Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 11421.50Skamil info.psi_siginfo.si_errno); 11431.50Skamil 11441.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 11451.50Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 11461.50Skamil 11471.50Skamil DPRINTF("Before resuming the child process where it left off and with " 11481.50Skamil "signal %s to be sent\n", strsignal(sigsent)); 11491.50Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 11501.50Skamil 11511.50Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 11521.50Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 11531.50Skamil 11541.50Skamil validate_status_exited(status, exitval); 11551.50Skamil 11561.50Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 11571.50Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 11581.50Skamil} 11591.50Skamil 11601.61Skre#define TRACEME_SENDSIGNAL_IGNORED(test, sig) \ 11611.61SkreATF_TC(test); \ 11621.61SkreATF_TC_HEAD(test, tc) \ 11631.61Skre{ \ 11641.61Skre atf_tc_set_md_var(tc, "descr", \ 11651.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 11661.61Skre "handled correctly and the signal is masked by SIG_IGN"); \ 11671.61Skre} \ 11681.61Skre \ 11691.61SkreATF_TC_BODY(test, tc) \ 11701.61Skre{ \ 11711.61Skre \ 11721.61Skre traceme_sendsignal_ignored(sig); \ 11731.50Skamil} 11741.50Skamil 11751.50Skamil// A signal handler for SIGKILL and SIGSTOP cannot be ignored. 11761.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored1, SIGABRT) /* abort */ 11771.50SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored2, SIGHUP) /* hangup */ 11781.61SkreTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored3, SIGCONT) /* continued */ 11791.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored4, SIGTRAP) /* crash s. */ 11801.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored5, SIGBUS) /* crash s. */ 11811.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored6, SIGILL) /* crash s. */ 11821.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored7, SIGFPE) /* crash s. */ 11831.85SkamilTRACEME_SENDSIGNAL_IGNORED(traceme_sendsignal_ignored8, SIGSEGV) /* crash s. */ 11841.50Skamil 11851.50Skamil/// ---------------------------------------------------------------------------- 11861.50Skamil 11871.50Skamilstatic void 11881.50Skamiltraceme_sendsignal_simple(int sigsent) 11891.1Skamil{ 11901.35Skamil const int sigval = SIGSTOP; 11911.35Skamil int exitval = 0; 11921.1Skamil pid_t child, wpid; 11931.1Skamil#if defined(TWAIT_HAVE_STATUS) 11941.1Skamil int status; 11951.85Skamil int expect_core; 11961.85Skamil 11971.85Skamil switch (sigsent) { 11981.85Skamil case SIGABRT: 11991.85Skamil case SIGTRAP: 12001.85Skamil case SIGBUS: 12011.85Skamil case SIGILL: 12021.85Skamil case SIGFPE: 12031.85Skamil case SIGSEGV: 12041.85Skamil expect_core = 1; 12051.85Skamil break; 12061.85Skamil default: 12071.85Skamil expect_core = 0; 12081.85Skamil break; 12091.85Skamil } 12101.1Skamil#endif 12111.61Skre struct ptrace_siginfo info; 12121.1Skamil 12131.45Skamil memset(&info, 0, sizeof(info)); 12141.45Skamil 12151.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 12161.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 12171.1Skamil if (child == 0) { 12181.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 12191.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 12201.1Skamil 12211.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 12221.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 12231.1Skamil 12241.35Skamil switch (sigsent) { 12251.35Skamil case SIGCONT: 12261.48Skamil case SIGSTOP: 12271.35Skamil _exit(exitval); 12281.35Skamil default: 12291.35Skamil /* NOTREACHED */ 12301.35Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 12311.35Skamil } 12321.1Skamil } 12331.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 12341.1Skamil 12351.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12361.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12371.1Skamil 12381.1Skamil validate_status_stopped(status, sigval); 12391.1Skamil 12401.45Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 12411.61Skre SYSCALL_REQUIRE( 12421.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 12431.45Skamil 12441.45Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12451.45Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 12461.45Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12471.45Skamil info.psi_siginfo.si_errno); 12481.45Skamil 12491.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12501.45Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12511.45Skamil 12521.13Schristos DPRINTF("Before resuming the child process where it left off and with " 12531.1Skamil "signal %s to be sent\n", strsignal(sigsent)); 12541.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, sigsent) != -1); 12551.1Skamil 12561.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12571.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12581.1Skamil 12591.35Skamil switch (sigsent) { 12601.48Skamil case SIGSTOP: 12611.48Skamil validate_status_stopped(status, sigsent); 12621.48Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 12631.61Skre "child\n"); 12641.48Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 12651.61Skre sizeof(info)) != -1); 12661.48Skamil 12671.48Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 12681.48Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 12691.61Skre "si_errno=%#x\n", 12701.61Skre info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 12711.61Skre info.psi_siginfo.si_errno); 12721.48Skamil 12731.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 12741.48Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 12751.48Skamil 12761.48Skamil DPRINTF("Before resuming the child process where it left off " 12771.61Skre "and with signal %s to be sent\n", strsignal(sigsent)); 12781.48Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 12791.48Skamil 12801.48Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12811.48Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 12821.61Skre child); 12831.48Skamil /* FALLTHROUGH */ 12841.35Skamil case SIGCONT: 12851.35Skamil validate_status_exited(status, exitval); 12861.35Skamil break; 12871.35Skamil default: 12881.35Skamil validate_status_signaled(status, sigsent, expect_core); 12891.35Skamil break; 12901.35Skamil } 12911.1Skamil 12921.13Schristos DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 12931.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 12941.1Skamil} 12951.1Skamil 12961.61Skre#define TRACEME_SENDSIGNAL_SIMPLE(test, sig) \ 12971.61SkreATF_TC(test); \ 12981.61SkreATF_TC_HEAD(test, tc) \ 12991.61Skre{ \ 13001.61Skre atf_tc_set_md_var(tc, "descr", \ 13011.61Skre "Verify that a signal " #sig " emitted by a tracer to a child is " \ 13021.61Skre "handled correctly in a child without a signal handler"); \ 13031.61Skre} \ 13041.61Skre \ 13051.61SkreATF_TC_BODY(test, tc) \ 13061.61Skre{ \ 13071.61Skre \ 13081.61Skre traceme_sendsignal_simple(sig); \ 13091.35Skamil} 13101.35Skamil 13111.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple1, SIGKILL) /* non-maskable*/ 13121.61SkreTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple2, SIGSTOP) /* non-maskable*/ 13131.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple3, SIGABRT) /* abort trap */ 13141.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple4, SIGHUP) /* hangup */ 13151.50SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple5, SIGCONT) /* continued? */ 13161.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple6, SIGTRAP) /* crash sig. */ 13171.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple7, SIGBUS) /* crash sig. */ 13181.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple8, SIGILL) /* crash sig. */ 13191.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple9, SIGFPE) /* crash sig. */ 13201.85SkamilTRACEME_SENDSIGNAL_SIMPLE(traceme_sendsignal_simple10, SIGSEGV) /* crash sig. */ 13211.35Skamil 13221.35Skamil/// ---------------------------------------------------------------------------- 13231.35Skamil 13241.37SkamilATF_TC(traceme_pid1_parent); 13251.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc) 13261.37Skamil{ 13271.37Skamil atf_tc_set_md_var(tc, "descr", 13281.37Skamil "Verify that PT_TRACE_ME is not allowed when our parent is PID1"); 13291.37Skamil} 13301.37Skamil 13311.37SkamilATF_TC_BODY(traceme_pid1_parent, tc) 13321.37Skamil{ 13331.37Skamil struct msg_fds parent_child; 13341.37Skamil int exitval_child1 = 1, exitval_child2 = 2; 13351.37Skamil pid_t child1, child2, wpid; 13361.37Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 13371.37Skamil#if defined(TWAIT_HAVE_STATUS) 13381.37Skamil int status; 13391.37Skamil#endif 13401.37Skamil 13411.37Skamil SYSCALL_REQUIRE(msg_open(&parent_child) == 0); 13421.37Skamil 13431.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13441.37Skamil SYSCALL_REQUIRE((child1 = fork()) != -1); 13451.37Skamil if (child1 == 0) { 13461.37Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 13471.37Skamil SYSCALL_REQUIRE((child2 = fork()) != -1); 13481.37Skamil if (child2 != 0) { 13491.37Skamil DPRINTF("Parent process PID=%d, child2's PID=%d\n", 13501.61Skre getpid(), child2); 13511.37Skamil _exit(exitval_child1); 13521.37Skamil } 13531.37Skamil CHILD_FROM_PARENT("exit child1", parent_child, msg); 13541.37Skamil 13551.37Skamil DPRINTF("Assert that our parent is PID1 (initproc)\n"); 13561.37Skamil FORKEE_ASSERT_EQ(getppid(), 1); 13571.37Skamil 13581.37Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 13591.37Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1); 13601.37Skamil SYSCALL_REQUIRE_ERRNO(errno, EPERM); 13611.37Skamil 13621.37Skamil CHILD_TO_PARENT("child2 exiting", parent_child, msg); 13631.37Skamil 13641.37Skamil _exit(exitval_child2); 13651.37Skamil } 13661.37Skamil DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1); 13671.37Skamil 13681.37Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 13691.61Skre TWAIT_REQUIRE_SUCCESS( 13701.61Skre wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1); 13711.37Skamil 13721.37Skamil validate_status_exited(status, exitval_child1); 13731.37Skamil 13741.37Skamil DPRINTF("Notify that child1 is dead\n"); 13751.37Skamil PARENT_TO_CHILD("exit child1", parent_child, msg); 13761.37Skamil 13771.37Skamil DPRINTF("Wait for exiting of child2\n"); 13781.37Skamil PARENT_FROM_CHILD("child2 exiting", parent_child, msg); 13791.37Skamil} 13801.37Skamil 13811.37Skamil/// ---------------------------------------------------------------------------- 13821.37Skamil 13831.40Skamilstatic void 13841.40Skamiltraceme_vfork_raise(int sigval) 13851.40Skamil{ 13861.46Skamil const int exitval = 5, exitval_watcher = 10; 13871.46Skamil pid_t child, parent, watcher, wpid; 13881.46Skamil int rv; 13891.40Skamil#if defined(TWAIT_HAVE_STATUS) 13901.40Skamil int status; 13911.85Skamil 13921.85Skamil /* volatile workarounds GCC -Werror=clobbered */ 13931.85Skamil volatile int expect_core; 13941.85Skamil 13951.85Skamil switch (sigval) { 13961.85Skamil case SIGABRT: 13971.85Skamil case SIGTRAP: 13981.85Skamil case SIGBUS: 13991.85Skamil case SIGILL: 14001.85Skamil case SIGFPE: 14011.85Skamil case SIGSEGV: 14021.85Skamil expect_core = 1; 14031.85Skamil break; 14041.85Skamil default: 14051.85Skamil expect_core = 0; 14061.85Skamil break; 14071.85Skamil } 14081.40Skamil#endif 14091.40Skamil 14101.46Skamil /* 14111.46Skamil * Spawn a dedicated thread to watch for a stopped child and emit 14121.46Skamil * the SIGKILL signal to it. 14131.46Skamil * 14141.46Skamil * vfork(2) might clobber watcher, this means that it's safer and 14151.46Skamil * simpler to reparent this process to initproc and forget about it. 14161.46Skamil */ 14171.46Skamil if (sigval == SIGSTOP) { 14181.46Skamil parent = getpid(); 14191.46Skamil 14201.46Skamil watcher = fork(); 14211.46Skamil ATF_REQUIRE(watcher != 1); 14221.46Skamil if (watcher == 0) { 14231.46Skamil /* Double fork(2) trick to reparent to initproc */ 14241.46Skamil watcher = fork(); 14251.46Skamil FORKEE_ASSERT_NEQ(watcher, -1); 14261.46Skamil if (watcher != 0) 14271.46Skamil _exit(exitval_watcher); 14281.46Skamil 14291.46Skamil child = await_stopped_child(parent); 14301.46Skamil 14311.46Skamil errno = 0; 14321.46Skamil rv = kill(child, SIGKILL); 14331.46Skamil FORKEE_ASSERT_EQ(rv, 0); 14341.46Skamil FORKEE_ASSERT_EQ(errno, 0); 14351.46Skamil 14361.46Skamil /* This exit value will be collected by initproc */ 14371.46Skamil _exit(0); 14381.46Skamil } 14391.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14401.46Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(watcher, &status, 0), 14411.61Skre watcher); 14421.46Skamil 14431.46Skamil validate_status_exited(status, exitval_watcher); 14441.46Skamil 14451.46Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14461.61Skre TWAIT_REQUIRE_FAILURE(ECHILD, 14471.61Skre wpid = TWAIT_GENERIC(watcher, &status, 0)); 14481.46Skamil } 14491.46Skamil 14501.40Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 14511.40Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 14521.40Skamil if (child == 0) { 14531.40Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 14541.40Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 14551.40Skamil 14561.40Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 14571.40Skamil FORKEE_ASSERT(raise(sigval) == 0); 14581.40Skamil 14591.40Skamil switch (sigval) { 14601.46Skamil case SIGSTOP: 14611.40Skamil case SIGKILL: 14621.40Skamil case SIGABRT: 14631.40Skamil case SIGHUP: 14641.85Skamil case SIGTRAP: 14651.85Skamil case SIGBUS: 14661.85Skamil case SIGILL: 14671.85Skamil case SIGFPE: 14681.85Skamil case SIGSEGV: 14691.40Skamil /* NOTREACHED */ 14701.40Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 14711.70Smrg __unreachable(); 14721.40Skamil default: 14731.40Skamil DPRINTF("Before exiting of the child process\n"); 14741.40Skamil _exit(exitval); 14751.40Skamil } 14761.40Skamil } 14771.40Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 14781.40Skamil 14791.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 14801.40Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 14811.40Skamil 14821.40Skamil switch (sigval) { 14831.40Skamil case SIGKILL: 14841.40Skamil case SIGABRT: 14851.40Skamil case SIGHUP: 14861.85Skamil case SIGTRAP: 14871.85Skamil case SIGBUS: 14881.85Skamil case SIGILL: 14891.85Skamil case SIGFPE: 14901.85Skamil case SIGSEGV: 14911.40Skamil validate_status_signaled(status, sigval, expect_core); 14921.40Skamil break; 14931.40Skamil case SIGSTOP: 14941.46Skamil validate_status_signaled(status, SIGKILL, 0); 14951.46Skamil break; 14961.40Skamil case SIGCONT: 14971.47Skamil case SIGTSTP: 14981.47Skamil case SIGTTIN: 14991.47Skamil case SIGTTOU: 15001.40Skamil validate_status_exited(status, exitval); 15011.40Skamil break; 15021.40Skamil default: 15031.40Skamil /* NOTREACHED */ 15041.40Skamil ATF_REQUIRE(0 && "NOT IMPLEMENTED"); 15051.40Skamil break; 15061.40Skamil } 15071.40Skamil 15081.40Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15091.40Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15101.40Skamil} 15111.40Skamil 15121.61Skre#define TRACEME_VFORK_RAISE(test, sig) \ 15131.61SkreATF_TC(test); \ 15141.61SkreATF_TC_HEAD(test, tc) \ 15151.61Skre{ \ 15161.61Skre atf_tc_set_md_var(tc, "descr", \ 15171.61Skre "Verify PT_TRACE_ME followed by raise of " #sig " in a " \ 15181.61Skre "vfork(2)ed child"); \ 15191.61Skre} \ 15201.61Skre \ 15211.61SkreATF_TC_BODY(test, tc) \ 15221.61Skre{ \ 15231.61Skre \ 15241.61Skre traceme_vfork_raise(sig); \ 15251.40Skamil} 15261.40Skamil 15271.40SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise1, SIGKILL) /* non-maskable */ 15281.46SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise2, SIGSTOP) /* non-maskable */ 15291.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise3, SIGTSTP) /* ignored in vfork(2) */ 15301.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise4, SIGTTIN) /* ignored in vfork(2) */ 15311.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise5, SIGTTOU) /* ignored in vfork(2) */ 15321.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise6, SIGABRT) /* regular abort trap */ 15331.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise7, SIGHUP) /* hangup */ 15341.47SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise8, SIGCONT) /* continued? */ 15351.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise9, SIGTRAP) /* crash signal */ 15361.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise10, SIGBUS) /* crash signal */ 15371.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise11, SIGILL) /* crash signal */ 15381.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise12, SIGFPE) /* crash signal */ 15391.85SkamilTRACEME_VFORK_RAISE(traceme_vfork_raise13, SIGSEGV) /* crash signal */ 15401.40Skamil 15411.40Skamil/// ---------------------------------------------------------------------------- 15421.40Skamil 15431.52Skamilstatic void 15441.52Skamiltraceme_vfork_crash(int sig) 15451.41Skamil{ 15461.41Skamil pid_t child, wpid; 15471.41Skamil#if defined(TWAIT_HAVE_STATUS) 15481.41Skamil int status; 15491.41Skamil#endif 15501.41Skamil 15511.71Skamil#ifndef PTRACE_ILLEGAL_ASM 15521.71Skamil if (sig == SIGILL) 15531.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 15541.71Skamil#endif 15551.71Skamil 15561.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 15571.114Skamil atf_tc_skip("FP exceptions are not supported"); 15581.114Skamil 15591.41Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 15601.41Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 15611.41Skamil if (child == 0) { 15621.41Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 15631.41Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 15641.41Skamil 15651.52Skamil DPRINTF("Before executing a trap\n"); 15661.52Skamil switch (sig) { 15671.52Skamil case SIGTRAP: 15681.52Skamil trigger_trap(); 15691.52Skamil break; 15701.52Skamil case SIGSEGV: 15711.52Skamil trigger_segv(); 15721.52Skamil break; 15731.52Skamil case SIGILL: 15741.52Skamil trigger_ill(); 15751.52Skamil break; 15761.52Skamil case SIGFPE: 15771.52Skamil trigger_fpe(); 15781.52Skamil break; 15791.52Skamil case SIGBUS: 15801.52Skamil trigger_bus(); 15811.52Skamil break; 15821.52Skamil default: 15831.52Skamil /* NOTREACHED */ 15841.52Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15851.52Skamil } 15861.41Skamil 15871.41Skamil /* NOTREACHED */ 15881.41Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 15891.41Skamil } 15901.41Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 15911.41Skamil 15921.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15931.41Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 15941.41Skamil 15951.52Skamil validate_status_signaled(status, sig, 1); 15961.41Skamil 15971.41Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15981.41Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 15991.41Skamil} 16001.41Skamil 16011.61Skre#define TRACEME_VFORK_CRASH(test, sig) \ 16021.61SkreATF_TC(test); \ 16031.61SkreATF_TC_HEAD(test, tc) \ 16041.61Skre{ \ 16051.61Skre atf_tc_set_md_var(tc, "descr", \ 16061.61Skre "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16071.61Skre "vfork(2)ed child"); \ 16081.61Skre} \ 16091.61Skre \ 16101.61SkreATF_TC_BODY(test, tc) \ 16111.61Skre{ \ 16121.61Skre \ 16131.61Skre traceme_vfork_crash(sig); \ 16141.52Skamil} 16151.52Skamil 16161.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_trap, SIGTRAP) 16171.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_segv, SIGSEGV) 16181.71SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_ill, SIGILL) 16191.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_fpe, SIGFPE) 16201.52SkamilTRACEME_VFORK_CRASH(traceme_vfork_crash_bus, SIGBUS) 16211.52Skamil 16221.41Skamil/// ---------------------------------------------------------------------------- 16231.41Skamil 16241.92Skamilstatic void 16251.92Skamiltraceme_vfork_signalmasked_crash(int sig) 16261.92Skamil{ 16271.92Skamil pid_t child, wpid; 16281.92Skamil#if defined(TWAIT_HAVE_STATUS) 16291.92Skamil int status; 16301.92Skamil#endif 16311.92Skamil sigset_t intmask; 16321.92Skamil 16331.92Skamil#ifndef PTRACE_ILLEGAL_ASM 16341.92Skamil if (sig == SIGILL) 16351.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 16361.92Skamil#endif 16371.92Skamil 16381.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 16391.114Skamil atf_tc_skip("FP exceptions are not supported"); 16401.114Skamil 16411.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 16421.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 16431.92Skamil if (child == 0) { 16441.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 16451.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 16461.92Skamil 16471.92Skamil sigemptyset(&intmask); 16481.92Skamil sigaddset(&intmask, sig); 16491.92Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 16501.92Skamil 16511.92Skamil DPRINTF("Before executing a trap\n"); 16521.92Skamil switch (sig) { 16531.92Skamil case SIGTRAP: 16541.92Skamil trigger_trap(); 16551.92Skamil break; 16561.92Skamil case SIGSEGV: 16571.92Skamil trigger_segv(); 16581.92Skamil break; 16591.92Skamil case SIGILL: 16601.92Skamil trigger_ill(); 16611.92Skamil break; 16621.92Skamil case SIGFPE: 16631.92Skamil trigger_fpe(); 16641.92Skamil break; 16651.92Skamil case SIGBUS: 16661.92Skamil trigger_bus(); 16671.92Skamil break; 16681.92Skamil default: 16691.92Skamil /* NOTREACHED */ 16701.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16711.92Skamil } 16721.92Skamil 16731.92Skamil /* NOTREACHED */ 16741.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 16751.92Skamil } 16761.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 16771.92Skamil 16781.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16791.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 16801.92Skamil 16811.92Skamil validate_status_signaled(status, sig, 1); 16821.92Skamil 16831.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16841.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 16851.92Skamil} 16861.92Skamil 16871.92Skamil#define TRACEME_VFORK_SIGNALMASKED_CRASH(test, sig) \ 16881.92SkamilATF_TC(test); \ 16891.92SkamilATF_TC_HEAD(test, tc) \ 16901.92Skamil{ \ 16911.92Skamil atf_tc_set_md_var(tc, "descr", \ 16921.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 16931.92Skamil "vfork(2)ed child with a masked signal"); \ 16941.92Skamil} \ 16951.92Skamil \ 16961.92SkamilATF_TC_BODY(test, tc) \ 16971.92Skamil{ \ 16981.92Skamil \ 16991.92Skamil traceme_vfork_signalmasked_crash(sig); \ 17001.92Skamil} 17011.92Skamil 17021.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_trap, SIGTRAP) 17031.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_segv, SIGSEGV) 17041.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_ill, SIGILL) 17051.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_fpe, SIGFPE) 17061.92SkamilTRACEME_VFORK_SIGNALMASKED_CRASH(traceme_vfork_signalmasked_crash_bus, SIGBUS) 17071.92Skamil 17081.92Skamil/// ---------------------------------------------------------------------------- 17091.92Skamil 17101.92Skamilstatic void 17111.92Skamiltraceme_vfork_signalignored_crash(int sig) 17121.92Skamil{ 17131.92Skamil pid_t child, wpid; 17141.92Skamil#if defined(TWAIT_HAVE_STATUS) 17151.92Skamil int status; 17161.92Skamil#endif 17171.92Skamil struct sigaction sa; 17181.92Skamil 17191.92Skamil#ifndef PTRACE_ILLEGAL_ASM 17201.92Skamil if (sig == SIGILL) 17211.92Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 17221.92Skamil#endif 17231.92Skamil 17241.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 17251.114Skamil atf_tc_skip("FP exceptions are not supported"); 17261.114Skamil 17271.92Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 17281.92Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 17291.92Skamil if (child == 0) { 17301.92Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 17311.92Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 17321.92Skamil 17331.92Skamil memset(&sa, 0, sizeof(sa)); 17341.92Skamil sa.sa_handler = SIG_IGN; 17351.92Skamil sigemptyset(&sa.sa_mask); 17361.92Skamil 17371.92Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 17381.92Skamil 17391.92Skamil DPRINTF("Before executing a trap\n"); 17401.92Skamil switch (sig) { 17411.92Skamil case SIGTRAP: 17421.92Skamil trigger_trap(); 17431.92Skamil break; 17441.92Skamil case SIGSEGV: 17451.92Skamil trigger_segv(); 17461.92Skamil break; 17471.92Skamil case SIGILL: 17481.92Skamil trigger_ill(); 17491.92Skamil break; 17501.92Skamil case SIGFPE: 17511.92Skamil trigger_fpe(); 17521.92Skamil break; 17531.92Skamil case SIGBUS: 17541.92Skamil trigger_bus(); 17551.92Skamil break; 17561.92Skamil default: 17571.92Skamil /* NOTREACHED */ 17581.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17591.92Skamil } 17601.92Skamil 17611.92Skamil /* NOTREACHED */ 17621.92Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 17631.92Skamil } 17641.92Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 17651.92Skamil 17661.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17671.92Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17681.92Skamil 17691.92Skamil validate_status_signaled(status, sig, 1); 17701.92Skamil 17711.92Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17721.92Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 17731.92Skamil} 17741.92Skamil 17751.92Skamil#define TRACEME_VFORK_SIGNALIGNORED_CRASH(test, sig) \ 17761.92SkamilATF_TC(test); \ 17771.92SkamilATF_TC_HEAD(test, tc) \ 17781.92Skamil{ \ 17791.92Skamil atf_tc_set_md_var(tc, "descr", \ 17801.92Skamil "Verify PT_TRACE_ME followed by a crash signal " #sig " in a " \ 17811.92Skamil "vfork(2)ed child with ignored signal"); \ 17821.92Skamil} \ 17831.92Skamil \ 17841.92SkamilATF_TC_BODY(test, tc) \ 17851.92Skamil{ \ 17861.92Skamil \ 17871.92Skamil traceme_vfork_signalignored_crash(sig); \ 17881.92Skamil} 17891.92Skamil 17901.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_trap, 17911.92Skamil SIGTRAP) 17921.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_segv, 17931.92Skamil SIGSEGV) 17941.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_ill, 17951.92Skamil SIGILL) 17961.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_fpe, 17971.92Skamil SIGFPE) 17981.92SkamilTRACEME_VFORK_SIGNALIGNORED_CRASH(traceme_vfork_signalignored_crash_bus, 17991.92Skamil SIGBUS) 18001.92Skamil 18011.92Skamil/// ---------------------------------------------------------------------------- 18021.92Skamil 18031.96Skamilstatic void 18041.96Skamiltraceme_vfork_exec(bool masked, bool ignored) 18051.43Skamil{ 18061.43Skamil const int sigval = SIGTRAP; 18071.43Skamil pid_t child, wpid; 18081.43Skamil#if defined(TWAIT_HAVE_STATUS) 18091.43Skamil int status; 18101.43Skamil#endif 18111.96Skamil struct sigaction sa; 18121.61Skre struct ptrace_siginfo info; 18131.96Skamil sigset_t intmask; 18141.96Skamil struct kinfo_proc2 kp; 18151.96Skamil size_t len = sizeof(kp); 18161.96Skamil 18171.96Skamil int name[6]; 18181.96Skamil const size_t namelen = __arraycount(name); 18191.96Skamil ki_sigset_t kp_sigmask; 18201.96Skamil ki_sigset_t kp_sigignore; 18211.43Skamil 18221.43Skamil memset(&info, 0, sizeof(info)); 18231.43Skamil 18241.43Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 18251.43Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 18261.43Skamil if (child == 0) { 18271.43Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 18281.43Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 18291.43Skamil 18301.96Skamil if (masked) { 18311.96Skamil sigemptyset(&intmask); 18321.96Skamil sigaddset(&intmask, sigval); 18331.96Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 18341.96Skamil } 18351.96Skamil 18361.96Skamil if (ignored) { 18371.96Skamil memset(&sa, 0, sizeof(sa)); 18381.96Skamil sa.sa_handler = SIG_IGN; 18391.96Skamil sigemptyset(&sa.sa_mask); 18401.96Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 18411.96Skamil } 18421.96Skamil 18431.43Skamil DPRINTF("Before calling execve(2) from child\n"); 18441.43Skamil execlp("/bin/echo", "/bin/echo", NULL); 18451.43Skamil 18461.43Skamil /* NOTREACHED */ 18471.43Skamil FORKEE_ASSERTX(0 && "Not reached"); 18481.43Skamil } 18491.43Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 18501.43Skamil 18511.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 18521.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 18531.43Skamil 18541.43Skamil validate_status_stopped(status, sigval); 18551.43Skamil 18561.96Skamil name[0] = CTL_KERN, 18571.96Skamil name[1] = KERN_PROC2, 18581.96Skamil name[2] = KERN_PROC_PID; 18591.96Skamil name[3] = getpid(); 18601.96Skamil name[4] = sizeof(kp); 18611.96Skamil name[5] = 1; 18621.96Skamil 18631.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18641.96Skamil 18651.96Skamil if (masked) 18661.96Skamil kp_sigmask = kp.p_sigmask; 18671.96Skamil 18681.96Skamil if (ignored) 18691.96Skamil kp_sigignore = kp.p_sigignore; 18701.96Skamil 18711.96Skamil name[3] = getpid(); 18721.96Skamil 18731.96Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 18741.96Skamil 18751.96Skamil if (masked) { 18761.96Skamil DPRINTF("kp_sigmask=" 18771.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18781.96Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 18791.96Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 18801.96Skamil 18811.96Skamil DPRINTF("kp.p_sigmask=" 18821.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18831.96Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 18841.96Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 18851.96Skamil 18861.96Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 18871.96Skamil sizeof(kp_sigmask))); 18881.96Skamil } 18891.96Skamil 18901.96Skamil if (ignored) { 18911.96Skamil DPRINTF("kp_sigignore=" 18921.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18931.96Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 18941.96Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 18951.96Skamil 18961.96Skamil DPRINTF("kp.p_sigignore=" 18971.96Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 18981.96Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 18991.96Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 19001.96Skamil 19011.96Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 19021.96Skamil sizeof(kp_sigignore))); 19031.96Skamil } 19041.96Skamil 19051.43Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 19061.61Skre SYSCALL_REQUIRE( 19071.61Skre ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 19081.43Skamil 19091.43Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 19101.43Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 19111.43Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 19121.43Skamil info.psi_siginfo.si_errno); 19131.43Skamil 19141.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 19151.43Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 19161.43Skamil 19171.43Skamil DPRINTF("Before resuming the child process where it left off and " 19181.43Skamil "without signal to be sent\n"); 19191.43Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 19201.43Skamil 19211.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19221.43Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 19231.43Skamil 19241.43Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 19251.43Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 19261.43Skamil} 19271.43Skamil 19281.96Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored) \ 19291.96SkamilATF_TC(test); \ 19301.96SkamilATF_TC_HEAD(test, tc) \ 19311.96Skamil{ \ 19321.96Skamil atf_tc_set_md_var(tc, "descr", \ 19331.96Skamil "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed " \ 19341.96Skamil "child%s%s", masked ? " with masked signal" : "", \ 19351.96Skamil masked ? " with ignored signal" : ""); \ 19361.96Skamil} \ 19371.96Skamil \ 19381.96SkamilATF_TC_BODY(test, tc) \ 19391.96Skamil{ \ 19401.96Skamil \ 19411.96Skamil traceme_vfork_exec(masked, ignored); \ 19421.96Skamil} 19431.96Skamil 19441.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false) 19451.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false) 19461.96SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true) 19471.96Skamil 19481.43Skamil/// ---------------------------------------------------------------------------- 19491.43Skamil 19501.1Skamil#if defined(TWAIT_HAVE_PID) 19511.51Skamilstatic void 19521.94Skamilunrelated_tracer_sees_crash(int sig, bool masked, bool ignored) 19531.59Skamil{ 19541.94Skamil const int sigval = SIGSTOP; 19551.59Skamil struct msg_fds parent_tracee, parent_tracer; 19561.59Skamil const int exitval = 10; 19571.59Skamil pid_t tracee, tracer, wpid; 19581.59Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 19591.59Skamil#if defined(TWAIT_HAVE_STATUS) 19601.59Skamil int status; 19611.59Skamil#endif 19621.94Skamil struct sigaction sa; 19631.59Skamil struct ptrace_siginfo info; 19641.94Skamil sigset_t intmask; 19651.94Skamil struct kinfo_proc2 kp; 19661.94Skamil size_t len = sizeof(kp); 19671.94Skamil 19681.94Skamil int name[6]; 19691.94Skamil const size_t namelen = __arraycount(name); 19701.94Skamil ki_sigset_t kp_sigmask; 19711.94Skamil ki_sigset_t kp_sigignore; 19721.61Skre 19731.71Skamil#ifndef PTRACE_ILLEGAL_ASM 19741.71Skamil if (sig == SIGILL) 19751.71Skamil atf_tc_skip("PTRACE_ILLEGAL_ASM not defined"); 19761.71Skamil#endif 19771.71Skamil 19781.114Skamil if (sig == SIGFPE && !are_fpu_exceptions_supported()) 19791.114Skamil atf_tc_skip("FP exceptions are not supported"); 19801.114Skamil 19811.59Skamil memset(&info, 0, sizeof(info)); 19821.59Skamil 19831.59Skamil DPRINTF("Spawn tracee\n"); 19841.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 19851.59Skamil tracee = atf_utils_fork(); 19861.59Skamil if (tracee == 0) { 19871.59Skamil // Wait for parent to let us crash 19881.59Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 19891.61Skre 19901.94Skamil if (masked) { 19911.94Skamil sigemptyset(&intmask); 19921.94Skamil sigaddset(&intmask, sig); 19931.94Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 19941.94Skamil } 19951.94Skamil 19961.94Skamil if (ignored) { 19971.94Skamil memset(&sa, 0, sizeof(sa)); 19981.94Skamil sa.sa_handler = SIG_IGN; 19991.94Skamil sigemptyset(&sa.sa_mask); 20001.94Skamil FORKEE_ASSERT(sigaction(sig, &sa, NULL) != -1); 20011.94Skamil } 20021.94Skamil 20031.94Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 20041.94Skamil FORKEE_ASSERT(raise(sigval) == 0); 20051.94Skamil 20061.59Skamil DPRINTF("Before executing a trap\n"); 20071.59Skamil switch (sig) { 20081.59Skamil case SIGTRAP: 20091.59Skamil trigger_trap(); 20101.59Skamil break; 20111.59Skamil case SIGSEGV: 20121.59Skamil trigger_segv(); 20131.59Skamil break; 20141.59Skamil case SIGILL: 20151.59Skamil trigger_ill(); 20161.59Skamil break; 20171.59Skamil case SIGFPE: 20181.59Skamil trigger_fpe(); 20191.59Skamil break; 20201.59Skamil case SIGBUS: 20211.59Skamil trigger_bus(); 20221.59Skamil break; 20231.59Skamil default: 20241.59Skamil /* NOTREACHED */ 20251.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20261.59Skamil } 20271.59Skamil 20281.59Skamil /* NOTREACHED */ 20291.59Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 20301.59Skamil } 20311.59Skamil 20321.59Skamil DPRINTF("Spawn debugger\n"); 20331.59Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 20341.59Skamil tracer = atf_utils_fork(); 20351.59Skamil if (tracer == 0) { 20361.59Skamil /* Fork again and drop parent to reattach to PID 1 */ 20371.59Skamil tracer = atf_utils_fork(); 20381.59Skamil if (tracer != 0) 20391.61Skre _exit(exitval); 20401.59Skamil 20411.59Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 20421.59Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 20431.59Skamil 20441.59Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 20451.59Skamil FORKEE_REQUIRE_SUCCESS( 20461.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20471.59Skamil 20481.59Skamil forkee_status_stopped(status, SIGSTOP); 20491.59Skamil 20501.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20511.94Skamil "traced process\n"); 20521.94Skamil SYSCALL_REQUIRE( 20531.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20541.94Skamil 20551.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20561.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20571.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20581.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20591.94Skamil 20601.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 20611.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 20621.94Skamil 20631.59Skamil /* Resume tracee with PT_CONTINUE */ 20641.59Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 20651.59Skamil 20661.59Skamil /* Inform parent that tracer has attached to tracee */ 20671.59Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 20681.59Skamil 20691.59Skamil /* Wait for parent to tell use that tracee should have exited */ 20701.59Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 20711.59Skamil 20721.59Skamil /* Wait for tracee and assert that it exited */ 20731.59Skamil FORKEE_REQUIRE_SUCCESS( 20741.59Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 20751.59Skamil 20761.94Skamil forkee_status_stopped(status, sigval); 20771.94Skamil 20781.94Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 20791.94Skamil "traced process\n"); 20801.94Skamil SYSCALL_REQUIRE( 20811.94Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 20821.94Skamil 20831.94Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20841.94Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 20851.94Skamil "si_errno=%#x\n", info.psi_siginfo.si_signo, 20861.94Skamil info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 20871.94Skamil 20881.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 20891.94Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 20901.94Skamil 20911.94Skamil name[0] = CTL_KERN, 20921.94Skamil name[1] = KERN_PROC2, 20931.94Skamil name[2] = KERN_PROC_PID; 20941.94Skamil name[3] = tracee; 20951.94Skamil name[4] = sizeof(kp); 20961.94Skamil name[5] = 1; 20971.94Skamil 20981.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 20991.94Skamil 21001.94Skamil if (masked) 21011.94Skamil kp_sigmask = kp.p_sigmask; 21021.94Skamil 21031.94Skamil if (ignored) 21041.94Skamil kp_sigignore = kp.p_sigignore; 21051.94Skamil 21061.94Skamil /* Resume tracee with PT_CONTINUE */ 21071.94Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 21081.94Skamil 21091.94Skamil /* Wait for tracee and assert that it exited */ 21101.94Skamil FORKEE_REQUIRE_SUCCESS( 21111.94Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21121.94Skamil 21131.93Skamil forkee_status_stopped(status, sig); 21141.59Skamil 21151.59Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for the " 21161.61Skre "traced process\n"); 21171.61Skre SYSCALL_REQUIRE( 21181.61Skre ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 21191.59Skamil 21201.59Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21211.59Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21221.61Skre "si_errno=%#x\n", info.psi_siginfo.si_signo, 21231.61Skre info.psi_siginfo.si_code, info.psi_siginfo.si_errno); 21241.59Skamil 21251.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sig); 21261.94Skamil 21271.94Skamil FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 21281.94Skamil 21291.94Skamil if (masked) { 21301.94Skamil DPRINTF("kp_sigmask=" 21311.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21321.94Skamil PRIx32 "\n", 21331.94Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 21341.94Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 21351.94Skamil 21361.94Skamil DPRINTF("kp.p_sigmask=" 21371.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21381.94Skamil PRIx32 "\n", 21391.94Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 21401.94Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 21411.94Skamil 21421.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigmask, &kp.p_sigmask, 21431.94Skamil sizeof(kp_sigmask))); 21441.94Skamil } 21451.94Skamil 21461.94Skamil if (ignored) { 21471.94Skamil DPRINTF("kp_sigignore=" 21481.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21491.94Skamil PRIx32 "\n", 21501.94Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 21511.94Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 21521.94Skamil 21531.94Skamil DPRINTF("kp.p_sigignore=" 21541.94Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" 21551.94Skamil PRIx32 "\n", 21561.94Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 21571.94Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 21581.94Skamil 21591.94Skamil FORKEE_ASSERTX(!memcmp(&kp_sigignore, &kp.p_sigignore, 21601.94Skamil sizeof(kp_sigignore))); 21611.94Skamil } 21621.94Skamil 21631.59Skamil switch (sig) { 21641.59Skamil case SIGTRAP: 21651.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, TRAP_BRKPT); 21661.59Skamil break; 21671.59Skamil case SIGSEGV: 21681.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SEGV_MAPERR); 21691.59Skamil break; 21701.71Skamil case SIGILL: 21711.113Skamil FORKEE_ASSERT(info.psi_siginfo.si_code >= ILL_ILLOPC && 21721.112Skamil info.psi_siginfo.si_code <= ILL_BADSTK); 21731.71Skamil break; 21741.59Skamil case SIGFPE: 21751.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, FPE_INTDIV); 21761.59Skamil break; 21771.59Skamil case SIGBUS: 21781.93Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, BUS_ADRERR); 21791.59Skamil break; 21801.59Skamil } 21811.59Skamil 21821.59Skamil FORKEE_ASSERT(ptrace(PT_KILL, tracee, NULL, 0) != -1); 21831.59Skamil DPRINTF("Before calling %s() for the tracee\n", TWAIT_FNAME); 21841.93Skamil FORKEE_REQUIRE_SUCCESS( 21851.61Skre wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 21861.59Skamil 21871.93Skamil forkee_status_signaled(status, SIGKILL, 0); 21881.59Skamil 21891.71Skamil /* Inform parent that tracer is exiting normally */ 21901.71Skamil CHILD_TO_PARENT("tracer done", parent_tracer, msg); 21911.71Skamil 21921.59Skamil DPRINTF("Before exiting of the tracer process\n"); 21931.59Skamil _exit(0 /* collect by initproc */); 21941.59Skamil } 21951.59Skamil 21961.59Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 21971.59Skamil "calling %s()\n", TWAIT_FNAME); 21981.59Skamil TWAIT_REQUIRE_SUCCESS( 21991.59Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 22001.59Skamil 22011.59Skamil validate_status_exited(status, exitval); 22021.59Skamil 22031.59Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 22041.59Skamil TWAIT_FNAME); 22051.59Skamil TWAIT_REQUIRE_SUCCESS( 22061.59Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 22071.59Skamil 22081.59Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 22091.59Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 22101.59Skamil 22111.59Skamil DPRINTF("Resume the tracee and let it crash\n"); 22121.59Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 22131.59Skamil 22141.59Skamil DPRINTF("Resume the tracer and let it detect crashed tracee\n"); 22151.59Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 22161.59Skamil 22171.59Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 22181.59Skamil TWAIT_FNAME); 22191.59Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 22201.59Skamil 22211.59Skamil validate_status_signaled(status, SIGKILL, 0); 22221.59Skamil 22231.71Skamil DPRINTF("Await normal exit of tracer\n"); 22241.71Skamil PARENT_FROM_CHILD("tracer done", parent_tracer, msg); 22251.71Skamil 22261.59Skamil msg_close(&parent_tracer); 22271.59Skamil msg_close(&parent_tracee); 22281.59Skamil} 22291.59Skamil 22301.61Skre#define UNRELATED_TRACER_SEES_CRASH(test, sig) \ 22311.61SkreATF_TC(test); \ 22321.61SkreATF_TC_HEAD(test, tc) \ 22331.61Skre{ \ 22341.61Skre atf_tc_set_md_var(tc, "descr", \ 22351.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22361.94Skamil "the debuggee"); \ 22371.61Skre} \ 22381.61Skre \ 22391.61SkreATF_TC_BODY(test, tc) \ 22401.61Skre{ \ 22411.61Skre \ 22421.94Skamil unrelated_tracer_sees_crash(sig, false, false); \ 22431.59Skamil} 22441.59Skamil 22451.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_trap, SIGTRAP) 22461.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_segv, SIGSEGV) 22471.71SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_ill, SIGILL) 22481.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_fpe, SIGFPE) 22491.59SkamilUNRELATED_TRACER_SEES_CRASH(unrelated_tracer_sees_crash_bus, SIGBUS) 22501.94Skamil 22511.94Skamil#define UNRELATED_TRACER_SEES_SIGNALMASKED_CRASH(test, sig) \ 22521.94SkamilATF_TC(test); \ 22531.94SkamilATF_TC_HEAD(test, tc) \ 22541.94Skamil{ \ 22551.94Skamil atf_tc_set_md_var(tc, "descr", \ 22561.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22571.94Skamil "the debuggee with masked signal"); \ 22581.94Skamil} \ 22591.94Skamil \ 22601.94SkamilATF_TC_BODY(test, tc) \ 22611.94Skamil{ \ 22621.94Skamil \ 22631.94Skamil unrelated_tracer_sees_crash(sig, true, false); \ 22641.94Skamil} 22651.94Skamil 22661.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22671.94Skamil unrelated_tracer_sees_signalmasked_crash_trap, SIGTRAP) 22681.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22691.94Skamil unrelated_tracer_sees_signalmasked_crash_segv, SIGSEGV) 22701.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22711.94Skamil unrelated_tracer_sees_signalmasked_crash_ill, SIGILL) 22721.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22731.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe, SIGFPE) 22741.94SkamilUNRELATED_TRACER_SEES_SIGNALMASKED_CRASH( 22751.94Skamil unrelated_tracer_sees_signalmasked_crash_bus, SIGBUS) 22761.94Skamil 22771.94Skamil#define UNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH(test, sig) \ 22781.94SkamilATF_TC(test); \ 22791.94SkamilATF_TC_HEAD(test, tc) \ 22801.94Skamil{ \ 22811.94Skamil atf_tc_set_md_var(tc, "descr", \ 22821.94Skamil "Assert that an unrelated tracer sees crash signal from " \ 22831.94Skamil "the debuggee with signal ignored"); \ 22841.94Skamil} \ 22851.94Skamil \ 22861.94SkamilATF_TC_BODY(test, tc) \ 22871.94Skamil{ \ 22881.94Skamil \ 22891.94Skamil unrelated_tracer_sees_crash(sig, false, true); \ 22901.94Skamil} 22911.94Skamil 22921.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22931.94Skamil unrelated_tracer_sees_signalignored_crash_trap, SIGTRAP) 22941.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22951.94Skamil unrelated_tracer_sees_signalignored_crash_segv, SIGSEGV) 22961.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22971.94Skamil unrelated_tracer_sees_signalignored_crash_ill, SIGILL) 22981.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 22991.94Skamil unrelated_tracer_sees_signalignored_crash_fpe, SIGFPE) 23001.94SkamilUNRELATED_TRACER_SEES_SIGNALIGNORED_CRASH( 23011.94Skamil unrelated_tracer_sees_signalignored_crash_bus, SIGBUS) 23021.59Skamil#endif 23031.59Skamil 23041.59Skamil/// ---------------------------------------------------------------------------- 23051.59Skamil 23061.59Skamil#if defined(TWAIT_HAVE_PID) 23071.59Skamilstatic void 23081.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated, 23091.67Skamil bool stopped) 23101.1Skamil{ 23111.51Skamil /* 23121.51Skamil * notimeout - disable timeout in await zombie function 23131.51Skamil * unrelated - attach from unrelated tracer reparented to initproc 23141.67Skamil * stopped - attach to a stopped process 23151.51Skamil */ 23161.1Skamil 23171.1Skamil struct msg_fds parent_tracee, parent_tracer; 23181.1Skamil const int exitval_tracee = 5; 23191.1Skamil const int exitval_tracer = 10; 23201.1Skamil pid_t tracee, tracer, wpid; 23211.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 23221.1Skamil#if defined(TWAIT_HAVE_STATUS) 23231.1Skamil int status; 23241.1Skamil#endif 23251.1Skamil 23261.67Skamil /* 23271.67Skamil * Only a subset of options are supported. 23281.67Skamil */ 23291.67Skamil ATF_REQUIRE((!notimeout && !unrelated && !stopped) || 23301.67Skamil (!notimeout && unrelated && !stopped) || 23311.67Skamil (notimeout && !unrelated && !stopped) || 23321.67Skamil (!notimeout && unrelated && stopped)); 23331.67Skamil 23341.13Schristos DPRINTF("Spawn tracee\n"); 23351.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 23361.1Skamil tracee = atf_utils_fork(); 23371.1Skamil if (tracee == 0) { 23381.67Skamil if (stopped) { 23391.67Skamil DPRINTF("Stop self PID %d\n", getpid()); 23401.67Skamil raise(SIGSTOP); 23411.67Skamil } 23421.67Skamil 23431.1Skamil // Wait for parent to let us exit 23441.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 23451.1Skamil _exit(exitval_tracee); 23461.1Skamil } 23471.1Skamil 23481.13Schristos DPRINTF("Spawn debugger\n"); 23491.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 23501.1Skamil tracer = atf_utils_fork(); 23511.1Skamil if (tracer == 0) { 23521.51Skamil if(unrelated) { 23531.51Skamil /* Fork again and drop parent to reattach to PID 1 */ 23541.51Skamil tracer = atf_utils_fork(); 23551.51Skamil if (tracer != 0) 23561.51Skamil _exit(exitval_tracer); 23571.51Skamil } 23581.51Skamil 23591.67Skamil if (stopped) { 23601.67Skamil DPRINTF("Await for a stopped parent PID %d\n", tracee); 23611.67Skamil await_stopped(tracee); 23621.67Skamil } 23631.67Skamil 23641.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 23651.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 23661.1Skamil 23671.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 23681.1Skamil FORKEE_REQUIRE_SUCCESS( 23691.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23701.1Skamil 23711.1Skamil forkee_status_stopped(status, SIGSTOP); 23721.1Skamil 23731.1Skamil /* Resume tracee with PT_CONTINUE */ 23741.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 23751.1Skamil 23761.1Skamil /* Inform parent that tracer has attached to tracee */ 23771.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 23781.1Skamil 23791.1Skamil /* Wait for parent to tell use that tracee should have exited */ 23801.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 23811.1Skamil 23821.1Skamil /* Wait for tracee and assert that it exited */ 23831.1Skamil FORKEE_REQUIRE_SUCCESS( 23841.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 23851.1Skamil 23861.1Skamil forkee_status_exited(status, exitval_tracee); 23871.13Schristos DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee); 23881.1Skamil 23891.13Schristos DPRINTF("Before exiting of the tracer process\n"); 23901.51Skamil _exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer); 23911.51Skamil } 23921.51Skamil 23931.51Skamil if (unrelated) { 23941.51Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 23951.51Skamil "calling %s()\n", TWAIT_FNAME); 23961.51Skamil TWAIT_REQUIRE_SUCCESS( 23971.51Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 23981.51Skamil 23991.51Skamil validate_status_exited(status, exitval_tracer); 24001.51Skamil 24011.51Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 24021.51Skamil TWAIT_FNAME); 24031.51Skamil TWAIT_REQUIRE_SUCCESS( 24041.51Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 24051.1Skamil } 24061.1Skamil 24071.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 24081.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 24091.1Skamil 24101.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 24111.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 24121.1Skamil 24131.13Schristos DPRINTF("Detect that tracee is zombie\n"); 24141.51Skamil if (notimeout) 24151.26Skamil await_zombie_raw(tracee, 0); 24161.26Skamil else 24171.26Skamil await_zombie(tracee); 24181.1Skamil 24191.13Schristos DPRINTF("Assert that there is no status about tracee %d - " 24201.1Skamil "Tracer must detect zombie first - calling %s()\n", tracee, 24211.1Skamil TWAIT_FNAME); 24221.1Skamil TWAIT_REQUIRE_SUCCESS( 24231.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 24241.1Skamil 24251.51Skamil if (unrelated) { 24261.51Skamil DPRINTF("Resume the tracer and let it detect exited tracee\n"); 24271.51Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 24281.51Skamil } else { 24291.51Skamil DPRINTF("Tell the tracer child should have exited\n"); 24301.51Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 24311.51Skamil DPRINTF("Wait for tracer to finish its job and exit - calling " 24321.59Skamil "%s()\n", TWAIT_FNAME); 24331.51Skamil 24341.51Skamil DPRINTF("Wait from tracer child to complete waiting for " 24351.59Skamil "tracee\n"); 24361.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 24371.51Skamil tracer); 24381.1Skamil 24391.51Skamil validate_status_exited(status, exitval_tracer); 24401.51Skamil } 24411.1Skamil 24421.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 24431.1Skamil TWAIT_FNAME); 24441.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 24451.1Skamil 24461.1Skamil validate_status_exited(status, exitval_tracee); 24471.1Skamil 24481.1Skamil msg_close(&parent_tracer); 24491.1Skamil msg_close(&parent_tracee); 24501.1Skamil} 24511.26Skamil 24521.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent); 24531.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc) 24541.51Skamil{ 24551.51Skamil atf_tc_set_md_var(tc, "descr", 24561.51Skamil "Assert that tracer sees process termination before the parent"); 24571.51Skamil} 24581.51Skamil 24591.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc) 24601.26Skamil{ 24611.26Skamil 24621.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, false, false); 24631.26Skamil} 24641.26Skamil 24651.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates); 24661.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc) 24671.1Skamil{ 24681.164Skamil atf_tc_set_md_var(tc, "timeout", "15"); 24691.1Skamil atf_tc_set_md_var(tc, "descr", 24701.51Skamil "Assert that await_zombie() in attach1 always finds a single " 24711.51Skamil "process and no other error is reported"); 24721.1Skamil} 24731.1Skamil 24741.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc) 24751.1Skamil{ 24761.51Skamil time_t start, end; 24771.51Skamil double diff; 24781.51Skamil unsigned long N = 0; 24791.1Skamil 24801.51Skamil /* 24811.51Skamil * Reuse this test with tracer_sees_terminaton_before_the_parent_raw(). 24821.51Skamil * This test body isn't specific to this race, however it's just good 24831.51Skamil * enough for this purposes, no need to invent a dedicated code flow. 24841.51Skamil */ 24851.1Skamil 24861.51Skamil start = time(NULL); 24871.51Skamil while (true) { 24881.51Skamil DPRINTF("Step: %lu\n", N); 24891.67Skamil tracer_sees_terminaton_before_the_parent_raw(true, false, 24901.67Skamil false); 24911.51Skamil end = time(NULL); 24921.51Skamil diff = difftime(end, start); 24931.51Skamil if (diff >= 5.0) 24941.51Skamil break; 24951.51Skamil ++N; 24961.1Skamil } 24971.51Skamil DPRINTF("Iterations: %lu\n", N); 24981.51Skamil} 24991.1Skamil 25001.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent); 25011.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc) 25021.51Skamil{ 25031.51Skamil atf_tc_set_md_var(tc, "descr", 25041.51Skamil "Assert that tracer sees process termination before the parent"); 25051.51Skamil} 25061.1Skamil 25071.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc) 25081.51Skamil{ 25091.1Skamil 25101.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, false); 25111.67Skamil} 25121.67Skamil 25131.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process); 25141.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc) 25151.67Skamil{ 25161.67Skamil atf_tc_set_md_var(tc, "descr", 25171.67Skamil "Assert that tracer can attach to an unrelated stopped process"); 25181.67Skamil} 25191.67Skamil 25201.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc) 25211.67Skamil{ 25221.67Skamil 25231.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, true); 25241.1Skamil} 25251.1Skamil#endif 25261.1Skamil 25271.51Skamil/// ---------------------------------------------------------------------------- 25281.51Skamil 25291.66Skamilstatic void 25301.66Skamilparent_attach_to_its_child(bool stopped) 25311.1Skamil{ 25321.1Skamil struct msg_fds parent_tracee; 25331.1Skamil const int exitval_tracee = 5; 25341.1Skamil pid_t tracee, wpid; 25351.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 25361.1Skamil#if defined(TWAIT_HAVE_STATUS) 25371.1Skamil int status; 25381.1Skamil#endif 25391.1Skamil 25401.13Schristos DPRINTF("Spawn tracee\n"); 25411.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 25421.1Skamil tracee = atf_utils_fork(); 25431.1Skamil if (tracee == 0) { 25441.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 25451.13Schristos DPRINTF("Parent should now attach to tracee\n"); 25461.1Skamil 25471.66Skamil if (stopped) { 25481.66Skamil DPRINTF("Stop self PID %d\n", getpid()); 25491.66Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 25501.66Skamil } 25511.66Skamil 25521.1Skamil CHILD_FROM_PARENT("Message 2", parent_tracee, msg); 25531.1Skamil /* Wait for message from the parent */ 25541.1Skamil _exit(exitval_tracee); 25551.1Skamil } 25561.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 25571.57Skamil 25581.66Skamil if (stopped) { 25591.66Skamil DPRINTF("Await for a stopped tracee PID %d\n", tracee); 25601.66Skamil await_stopped(tracee); 25611.66Skamil } 25621.66Skamil 25631.13Schristos DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee); 25641.13Schristos SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 25651.1Skamil 25661.13Schristos DPRINTF("Wait for the stopped tracee process with %s()\n", 25671.1Skamil TWAIT_FNAME); 25681.1Skamil TWAIT_REQUIRE_SUCCESS( 25691.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25701.1Skamil 25711.1Skamil validate_status_stopped(status, SIGSTOP); 25721.1Skamil 25731.13Schristos DPRINTF("Resume tracee with PT_CONTINUE\n"); 25741.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 25751.1Skamil 25761.13Schristos DPRINTF("Let the tracee exit now\n"); 25771.1Skamil PARENT_TO_CHILD("Message 2", parent_tracee, msg); 25781.1Skamil 25791.13Schristos DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME); 25801.1Skamil TWAIT_REQUIRE_SUCCESS( 25811.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 25821.1Skamil 25831.1Skamil validate_status_exited(status, exitval_tracee); 25841.1Skamil 25851.13Schristos DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME); 25861.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 25871.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0)); 25881.1Skamil 25891.1Skamil msg_close(&parent_tracee); 25901.1Skamil} 25911.1Skamil 25921.66SkamilATF_TC(parent_attach_to_its_child); 25931.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc) 25941.66Skamil{ 25951.66Skamil atf_tc_set_md_var(tc, "descr", 25961.66Skamil "Assert that tracer parent can PT_ATTACH to its child"); 25971.66Skamil} 25981.66Skamil 25991.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc) 26001.66Skamil{ 26011.66Skamil 26021.66Skamil parent_attach_to_its_child(false); 26031.66Skamil} 26041.66Skamil 26051.66SkamilATF_TC(parent_attach_to_its_stopped_child); 26061.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc) 26071.66Skamil{ 26081.66Skamil atf_tc_set_md_var(tc, "descr", 26091.66Skamil "Assert that tracer parent can PT_ATTACH to its stopped child"); 26101.66Skamil} 26111.66Skamil 26121.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc) 26131.66Skamil{ 26141.66Skamil 26151.66Skamil parent_attach_to_its_child(true); 26161.66Skamil} 26171.66Skamil 26181.51Skamil/// ---------------------------------------------------------------------------- 26191.51Skamil 26201.65Skamilstatic void 26211.65Skamilchild_attach_to_its_parent(bool stopped) 26221.1Skamil{ 26231.1Skamil struct msg_fds parent_tracee; 26241.1Skamil const int exitval_tracer = 5; 26251.1Skamil pid_t tracer, wpid; 26261.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 26271.1Skamil#if defined(TWAIT_HAVE_STATUS) 26281.1Skamil int status; 26291.1Skamil#endif 26301.1Skamil 26311.13Schristos DPRINTF("Spawn tracer\n"); 26321.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 26331.1Skamil tracer = atf_utils_fork(); 26341.1Skamil if (tracer == 0) { 26351.1Skamil /* Wait for message from the parent */ 26361.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 26371.1Skamil 26381.65Skamil if (stopped) { 26391.65Skamil DPRINTF("Await for a stopped parent PID %d\n", 26401.65Skamil getppid()); 26411.65Skamil await_stopped(getppid()); 26421.65Skamil } 26431.65Skamil 26441.13Schristos DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n", 26451.1Skamil getppid()); 26461.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1); 26471.1Skamil 26481.13Schristos DPRINTF("Wait for the stopped parent process with %s()\n", 26491.1Skamil TWAIT_FNAME); 26501.1Skamil FORKEE_REQUIRE_SUCCESS( 26511.1Skamil wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid()); 26521.1Skamil 26531.1Skamil forkee_status_stopped(status, SIGSTOP); 26541.1Skamil 26551.13Schristos DPRINTF("Resume parent with PT_DETACH\n"); 26561.1Skamil FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0) 26571.1Skamil != -1); 26581.1Skamil 26591.1Skamil /* Tell parent we are ready */ 26601.1Skamil CHILD_TO_PARENT("Message 1", parent_tracee, msg); 26611.1Skamil 26621.1Skamil _exit(exitval_tracer); 26631.1Skamil } 26641.1Skamil 26651.13Schristos DPRINTF("Wait for the tracer to become ready\n"); 26661.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 26671.65Skamil 26681.65Skamil if (stopped) { 26691.65Skamil DPRINTF("Stop self PID %d\n", getpid()); 26701.65Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 26711.65Skamil } 26721.65Skamil 26731.13Schristos DPRINTF("Allow the tracer to exit now\n"); 26741.1Skamil PARENT_FROM_CHILD("Message 1", parent_tracee, msg); 26751.1Skamil 26761.13Schristos DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME); 26771.1Skamil TWAIT_REQUIRE_SUCCESS( 26781.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 26791.1Skamil 26801.1Skamil validate_status_exited(status, exitval_tracer); 26811.1Skamil 26821.13Schristos DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME); 26831.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 26841.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0)); 26851.1Skamil 26861.1Skamil msg_close(&parent_tracee); 26871.1Skamil} 26881.1Skamil 26891.65SkamilATF_TC(child_attach_to_its_parent); 26901.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc) 26911.65Skamil{ 26921.65Skamil atf_tc_set_md_var(tc, "descr", 26931.65Skamil "Assert that tracer child can PT_ATTACH to its parent"); 26941.65Skamil} 26951.65Skamil 26961.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc) 26971.65Skamil{ 26981.65Skamil 26991.65Skamil child_attach_to_its_parent(false); 27001.65Skamil} 27011.65Skamil 27021.65SkamilATF_TC(child_attach_to_its_stopped_parent); 27031.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc) 27041.65Skamil{ 27051.65Skamil atf_tc_set_md_var(tc, "descr", 27061.65Skamil "Assert that tracer child can PT_ATTACH to its stopped parent"); 27071.65Skamil} 27081.65Skamil 27091.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc) 27101.65Skamil{ 27111.65Skamil /* 27121.65Skamil * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as 27131.65Skamil * this causes a pipe (established from atf-run) to be broken. 27141.65Skamil * atf-run uses this mechanism to monitor whether a test is alive. 27151.65Skamil * 27161.65Skamil * As a workaround spawn this test as a subprocess. 27171.65Skamil */ 27181.65Skamil 27191.65Skamil const int exitval = 15; 27201.65Skamil pid_t child, wpid; 27211.65Skamil#if defined(TWAIT_HAVE_STATUS) 27221.65Skamil int status; 27231.65Skamil#endif 27241.65Skamil 27251.65Skamil SYSCALL_REQUIRE((child = fork()) != -1); 27261.65Skamil if (child == 0) { 27271.65Skamil child_attach_to_its_parent(true); 27281.65Skamil _exit(exitval); 27291.65Skamil } else { 27301.65Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 27311.65Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 27321.65Skamil 27331.65Skamil validate_status_exited(status, exitval); 27341.65Skamil 27351.65Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 27361.65Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 27371.65Skamil } 27381.65Skamil} 27391.65Skamil 27401.51Skamil/// ---------------------------------------------------------------------------- 27411.51Skamil 27421.1Skamil#if defined(TWAIT_HAVE_PID) 27431.1Skamil 27441.51Skamilenum tracee_sees_its_original_parent_type { 27451.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 27461.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 27471.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS 27481.51Skamil}; 27491.51Skamil 27501.51Skamilstatic void 27511.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type) 27521.1Skamil{ 27531.1Skamil struct msg_fds parent_tracer, parent_tracee; 27541.1Skamil const int exitval_tracee = 5; 27551.1Skamil const int exitval_tracer = 10; 27561.1Skamil pid_t parent, tracee, tracer, wpid; 27571.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 27581.1Skamil#if defined(TWAIT_HAVE_STATUS) 27591.1Skamil int status; 27601.1Skamil#endif 27611.51Skamil /* sysctl(3) - kinfo_proc2 */ 27621.51Skamil int name[CTL_MAXNAME]; 27631.51Skamil struct kinfo_proc2 kp; 27641.51Skamil size_t len = sizeof(kp); 27651.51Skamil unsigned int namelen; 27661.51Skamil 27671.51Skamil /* procfs - status */ 27681.51Skamil FILE *fp; 27691.51Skamil struct stat st; 27701.51Skamil const char *fname = "/proc/curproc/status"; 27711.51Skamil char s_executable[MAXPATHLEN]; 27721.51Skamil int s_pid, s_ppid; 27731.51Skamil int rv; 27741.51Skamil 27751.51Skamil if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) { 27761.61Skre SYSCALL_REQUIRE( 27771.61Skre (rv = stat(fname, &st)) == 0 || (errno == ENOENT)); 27781.61Skre if (rv != 0) 27791.51Skamil atf_tc_skip("/proc/curproc/status not found"); 27801.51Skamil } 27811.1Skamil 27821.13Schristos DPRINTF("Spawn tracee\n"); 27831.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 27841.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 27851.1Skamil tracee = atf_utils_fork(); 27861.1Skamil if (tracee == 0) { 27871.1Skamil parent = getppid(); 27881.1Skamil 27891.1Skamil /* Emit message to the parent */ 27901.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 27911.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 27921.1Skamil 27931.51Skamil switch (type) { 27941.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID: 27951.51Skamil FORKEE_ASSERT_EQ(parent, getppid()); 27961.51Skamil break; 27971.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2: 27981.51Skamil namelen = 0; 27991.51Skamil name[namelen++] = CTL_KERN; 28001.51Skamil name[namelen++] = KERN_PROC2; 28011.51Skamil name[namelen++] = KERN_PROC_PID; 28021.51Skamil name[namelen++] = getpid(); 28031.51Skamil name[namelen++] = len; 28041.51Skamil name[namelen++] = 1; 28051.51Skamil 28061.61Skre FORKEE_ASSERT_EQ( 28071.61Skre sysctl(name, namelen, &kp, &len, NULL, 0), 0); 28081.51Skamil FORKEE_ASSERT_EQ(parent, kp.p_ppid); 28091.51Skamil break; 28101.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS: 28111.51Skamil /* 28121.51Skamil * Format: 28131.51Skamil * EXECUTABLE PID PPID ... 28141.51Skamil */ 28151.51Skamil FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL); 28161.51Skamil fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid); 28171.51Skamil FORKEE_ASSERT_EQ(fclose(fp), 0); 28181.51Skamil FORKEE_ASSERT_EQ(parent, s_ppid); 28191.51Skamil break; 28201.51Skamil } 28211.1Skamil 28221.1Skamil _exit(exitval_tracee); 28231.1Skamil } 28241.13Schristos DPRINTF("Wait for child to record its parent identifier (pid)\n"); 28251.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 28261.1Skamil 28271.13Schristos DPRINTF("Spawn debugger\n"); 28281.1Skamil tracer = atf_utils_fork(); 28291.1Skamil if (tracer == 0) { 28301.1Skamil /* No IPC to communicate with the child */ 28311.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 28321.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 28331.1Skamil 28341.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 28351.1Skamil FORKEE_REQUIRE_SUCCESS( 28361.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28371.1Skamil 28381.1Skamil forkee_status_stopped(status, SIGSTOP); 28391.1Skamil 28401.1Skamil /* Resume tracee with PT_CONTINUE */ 28411.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 28421.1Skamil 28431.1Skamil /* Inform parent that tracer has attached to tracee */ 28441.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 28451.1Skamil 28461.1Skamil /* Wait for parent to tell use that tracee should have exited */ 28471.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 28481.1Skamil 28491.1Skamil /* Wait for tracee and assert that it exited */ 28501.1Skamil FORKEE_REQUIRE_SUCCESS( 28511.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 28521.1Skamil 28531.1Skamil forkee_status_exited(status, exitval_tracee); 28541.1Skamil 28551.13Schristos DPRINTF("Before exiting of the tracer process\n"); 28561.1Skamil _exit(exitval_tracer); 28571.1Skamil } 28581.1Skamil 28591.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 28601.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 28611.1Skamil 28621.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 28631.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 28641.1Skamil 28651.13Schristos DPRINTF("Detect that tracee is zombie\n"); 28661.1Skamil await_zombie(tracee); 28671.1Skamil 28681.13Schristos DPRINTF("Assert that there is no status about tracee - " 28691.1Skamil "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME); 28701.1Skamil TWAIT_REQUIRE_SUCCESS( 28711.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 28721.1Skamil 28731.13Schristos DPRINTF("Tell the tracer child should have exited\n"); 28741.1Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 28751.1Skamil 28761.13Schristos DPRINTF("Wait from tracer child to complete waiting for tracee\n"); 28771.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 28781.1Skamil tracer); 28791.1Skamil 28801.1Skamil validate_status_exited(status, exitval_tracer); 28811.1Skamil 28821.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 28831.1Skamil TWAIT_FNAME); 28841.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 28851.1Skamil tracee); 28861.1Skamil 28871.1Skamil validate_status_exited(status, exitval_tracee); 28881.1Skamil 28891.1Skamil msg_close(&parent_tracer); 28901.1Skamil msg_close(&parent_tracee); 28911.1Skamil} 28921.1Skamil 28931.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr) \ 28941.61SkreATF_TC(test); \ 28951.61SkreATF_TC_HEAD(test, tc) \ 28961.61Skre{ \ 28971.61Skre atf_tc_set_md_var(tc, "descr", \ 28981.61Skre "Assert that tracee sees its original parent when being traced " \ 28991.61Skre "(check " descr ")"); \ 29001.61Skre} \ 29011.61Skre \ 29021.61SkreATF_TC_BODY(test, tc) \ 29031.61Skre{ \ 29041.61Skre \ 29051.61Skre tracee_sees_its_original_parent(type); \ 29061.1Skamil} 29071.1Skamil 29081.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29091.51Skamil tracee_sees_its_original_parent_getppid, 29101.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 29111.51Skamil "getppid(2)"); 29121.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29131.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2, 29141.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 29151.51Skamil "sysctl(3) and kinfo_proc2"); 29161.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 29171.51Skamil tracee_sees_its_original_parent_procfs_status, 29181.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS, 29191.51Skamil "the status file in procfs"); 29201.1Skamil#endif 29211.1Skamil 29221.51Skamil/// ---------------------------------------------------------------------------- 29231.1Skamil 29241.53Skamilstatic void 29251.53Skamileventmask_preserved(int event) 29261.1Skamil{ 29271.1Skamil const int exitval = 5; 29281.1Skamil const int sigval = SIGSTOP; 29291.1Skamil pid_t child, wpid; 29301.1Skamil#if defined(TWAIT_HAVE_STATUS) 29311.1Skamil int status; 29321.1Skamil#endif 29331.1Skamil ptrace_event_t set_event, get_event; 29341.1Skamil const int len = sizeof(ptrace_event_t); 29351.1Skamil 29361.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 29371.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 29381.1Skamil if (child == 0) { 29391.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 29401.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 29411.1Skamil 29421.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 29431.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 29441.1Skamil 29451.13Schristos DPRINTF("Before exiting of the child process\n"); 29461.1Skamil _exit(exitval); 29471.1Skamil } 29481.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 29491.1Skamil 29501.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29511.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29521.1Skamil 29531.1Skamil validate_status_stopped(status, sigval); 29541.1Skamil 29551.53Skamil set_event.pe_set_event = event; 29561.61Skre SYSCALL_REQUIRE( 29571.61Skre ptrace(PT_SET_EVENT_MASK, child, &set_event, len) != -1); 29581.61Skre SYSCALL_REQUIRE( 29591.61Skre ptrace(PT_GET_EVENT_MASK, child, &get_event, len) != -1); 29601.125Skamil DPRINTF("set_event=%#x get_event=%#x\n", set_event.pe_set_event, 29611.125Skamil get_event.pe_set_event); 29621.1Skamil ATF_REQUIRE(memcmp(&set_event, &get_event, len) == 0); 29631.1Skamil 29641.13Schristos DPRINTF("Before resuming the child process where it left off and " 29651.1Skamil "without signal to be sent\n"); 29661.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 29671.1Skamil 29681.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29691.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29701.1Skamil 29711.1Skamil validate_status_exited(status, exitval); 29721.1Skamil 29731.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29741.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 29751.1Skamil} 29761.1Skamil 29771.61Skre#define EVENTMASK_PRESERVED(test, event) \ 29781.61SkreATF_TC(test); \ 29791.61SkreATF_TC_HEAD(test, tc) \ 29801.61Skre{ \ 29811.61Skre atf_tc_set_md_var(tc, "descr", \ 29821.61Skre "Verify that eventmask " #event " is preserved"); \ 29831.61Skre} \ 29841.61Skre \ 29851.61SkreATF_TC_BODY(test, tc) \ 29861.61Skre{ \ 29871.61Skre \ 29881.61Skre eventmask_preserved(event); \ 29891.1Skamil} 29901.1Skamil 29911.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_empty, 0) 29921.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_fork, PTRACE_FORK) 29931.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork, PTRACE_VFORK) 29941.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_vfork_done, PTRACE_VFORK_DONE) 29951.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_create, PTRACE_LWP_CREATE) 29961.53SkamilEVENTMASK_PRESERVED(eventmask_preserved_lwp_exit, PTRACE_LWP_EXIT) 29971.125SkamilEVENTMASK_PRESERVED(eventmask_preserved_posix_spawn, PTRACE_POSIX_SPAWN) 29981.1Skamil 29991.53Skamil/// ---------------------------------------------------------------------------- 30001.1Skamil 30011.180Skamilstatic int lwpinfo_thread_sigmask[] = {SIGXCPU, SIGPIPE, SIGALRM, SIGURG}; 30021.180Skamil 30031.180Skamilstatic pthread_mutex_t lwpinfo_thread_mtx = PTHREAD_MUTEX_INITIALIZER; 30041.180Skamilstatic pthread_cond_t lwpinfo_thread_cnd = PTHREAD_COND_INITIALIZER; 30051.180Skamilstatic volatile size_t lwpinfo_thread_done; 30061.180Skamil 30071.180Skamilstatic void * 30081.180Skamillwpinfo_thread(void *arg) 30091.180Skamil{ 30101.180Skamil sigset_t s; 30111.180Skamil volatile void **tcb; 30121.180Skamil 30131.180Skamil tcb = (volatile void **)arg; 30141.180Skamil 30151.180Skamil *tcb = _lwp_getprivate(); 30161.180Skamil DPRINTF("Storing tcb[] = %p from thread %d\n", *tcb, _lwp_self()); 30171.180Skamil 30181.180Skamil pthread_setname_np(pthread_self(), "thread %d", 30191.180Skamil (void *)(intptr_t)_lwp_self()); 30201.180Skamil 30211.180Skamil sigemptyset(&s); 30221.180Skamil pthread_mutex_lock(&lwpinfo_thread_mtx); 30231.180Skamil sigaddset(&s, lwpinfo_thread_sigmask[lwpinfo_thread_done]); 30241.180Skamil lwpinfo_thread_done++; 30251.180Skamil pthread_sigmask(SIG_BLOCK, &s, NULL); 30261.180Skamil pthread_cond_signal(&lwpinfo_thread_cnd); 30271.180Skamil pthread_mutex_unlock(&lwpinfo_thread_mtx); 30281.180Skamil 30291.180Skamil return infinite_thread(NULL); 30301.180Skamil} 30311.180Skamil 30321.28Skamilstatic void 30331.180Skamiltraceme_lwpinfo(const size_t threads, const char *iter) 30341.1Skamil{ 30351.1Skamil const int sigval = SIGSTOP; 30361.180Skamil const int sigval2 = SIGINT; 30371.180Skamil pid_t child, wpid; 30381.1Skamil#if defined(TWAIT_HAVE_STATUS) 30391.1Skamil int status; 30401.1Skamil#endif 30411.180Skamil struct ptrace_lwpinfo lwp = {0, 0}; 30421.180Skamil struct ptrace_lwpstatus lwpstatus = {0}; 30431.180Skamil struct ptrace_siginfo info; 30441.180Skamil void *private; 30451.180Skamil char *name; 30461.180Skamil char namebuf[PL_LNAMELEN]; 30471.180Skamil volatile void *tcb[4]; 30481.180Skamil bool found; 30491.180Skamil sigset_t s; 30501.180Skamil 30511.180Skamil /* Maximum number of supported threads in this test */ 30521.180Skamil pthread_t t[__arraycount(tcb) - 1]; 30531.180Skamil size_t n, m; 30541.180Skamil int rv; 30551.180Skamil size_t bytes_read; 30561.180Skamil 30571.180Skamil struct ptrace_io_desc io; 30581.180Skamil sigset_t sigmask; 30591.1Skamil 30601.180Skamil ATF_REQUIRE(__arraycount(t) >= threads); 30611.180Skamil memset(tcb, 0, sizeof(tcb)); 30621.124Skamil 30631.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 30641.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 30651.1Skamil if (child == 0) { 30661.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 30671.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 30681.1Skamil 30691.180Skamil tcb[0] = _lwp_getprivate(); 30701.180Skamil DPRINTF("Storing tcb[0] = %p\n", tcb[0]); 30711.180Skamil 30721.180Skamil pthread_setname_np(pthread_self(), "thread %d", 30731.180Skamil (void *)(intptr_t)_lwp_self()); 30741.180Skamil 30751.180Skamil sigemptyset(&s); 30761.180Skamil sigaddset(&s, lwpinfo_thread_sigmask[lwpinfo_thread_done]); 30771.180Skamil pthread_sigmask(SIG_BLOCK, &s, NULL); 30781.180Skamil 30791.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 30801.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 30811.1Skamil 30821.180Skamil for (n = 0; n < threads; n++) { 30831.180Skamil rv = pthread_create(&t[n], NULL, lwpinfo_thread, 30841.180Skamil &tcb[n + 1]); 30851.180Skamil FORKEE_ASSERT(rv == 0); 30861.180Skamil } 30871.1Skamil 30881.180Skamil pthread_mutex_lock(&lwpinfo_thread_mtx); 30891.180Skamil while (lwpinfo_thread_done < threads) { 30901.180Skamil pthread_cond_wait(&lwpinfo_thread_cnd, 30911.180Skamil &lwpinfo_thread_mtx); 30921.124Skamil } 30931.180Skamil pthread_mutex_unlock(&lwpinfo_thread_mtx); 30941.1Skamil 30951.180Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval2)); 30961.180Skamil FORKEE_ASSERT(raise(sigval2) == 0); 30971.1Skamil 30981.180Skamil /* NOTREACHED */ 30991.180Skamil FORKEE_ASSERTX(0 && "Not reached"); 31001.1Skamil } 31011.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 31021.1Skamil 31031.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 31041.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31051.1Skamil 31061.1Skamil validate_status_stopped(status, sigval); 31071.1Skamil 31081.180Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 31091.180Skamil SYSCALL_REQUIRE( 31101.180Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 31111.1Skamil 31121.180Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 31131.180Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 31141.180Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 31151.180Skamil info.psi_siginfo.si_errno); 31161.1Skamil 31171.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 31181.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 31191.1Skamil 31201.180Skamil if (strstr(iter, "LWPINFO") != NULL) { 31211.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 31221.180Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) 31231.180Skamil != -1); 31241.1Skamil 31251.180Skamil DPRINTF("Assert that there exists a single thread only\n"); 31261.180Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 31271.1Skamil 31281.180Skamil DPRINTF("Assert that lwp thread %d received event " 31291.180Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 31301.180Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 31311.1Skamil 31321.180Skamil if (strstr(iter, "LWPSTATUS") != NULL) { 31331.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPSTATUS " 31341.180Skamil "for child\n"); 31351.180Skamil lwpstatus.pl_lwpid = lwp.pl_lwpid; 31361.180Skamil SYSCALL_REQUIRE(ptrace(PT_LWPSTATUS, child, &lwpstatus, 31371.180Skamil sizeof(lwpstatus)) != -1); 31381.30Skamil } 31391.30Skamil 31401.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 31411.180Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) 31421.180Skamil != -1); 31431.29Skamil 31441.180Skamil DPRINTF("Assert that there exists a single thread only\n"); 31451.180Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 31461.180Skamil } else { 31471.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for child\n"); 31481.180Skamil SYSCALL_REQUIRE(ptrace(PT_LWPNEXT, child, &lwpstatus, 31491.180Skamil sizeof(lwpstatus)) != -1); 31501.29Skamil 31511.180Skamil DPRINTF("Assert that there exists a single thread only %d\n", lwpstatus.pl_lwpid); 31521.180Skamil ATF_REQUIRE(lwpstatus.pl_lwpid > 0); 31531.30Skamil 31541.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for child\n"); 31551.180Skamil SYSCALL_REQUIRE(ptrace(PT_LWPNEXT, child, &lwpstatus, 31561.180Skamil sizeof(lwpstatus)) != -1); 31571.30Skamil 31581.180Skamil DPRINTF("Assert that there exists a single thread only\n"); 31591.180Skamil ATF_REQUIRE_EQ(lwpstatus.pl_lwpid, 0); 31601.30Skamil } 31611.29Skamil 31621.13Schristos DPRINTF("Before resuming the child process where it left off and " 31631.1Skamil "without signal to be sent\n"); 31641.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 31651.1Skamil 31661.180Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 31671.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 31681.1Skamil 31691.180Skamil validate_status_stopped(status, sigval2); 31701.180Skamil 31711.180Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 31721.180Skamil SYSCALL_REQUIRE( 31731.180Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 31741.180Skamil 31751.180Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 31761.180Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 31771.180Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 31781.180Skamil info.psi_siginfo.si_errno); 31791.1Skamil 31801.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2); 31811.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 31821.28Skamil 31831.180Skamil memset(&lwp, 0, sizeof(lwp)); 31841.180Skamil memset(&lwpstatus, 0, sizeof(lwpstatus)); 31851.32Skamil 31861.180Skamil memset(&io, 0, sizeof(io)); 31871.1Skamil 31881.180Skamil bytes_read = 0; 31891.180Skamil io.piod_op = PIOD_READ_D; 31901.180Skamil io.piod_len = sizeof(tcb); 31911.125Skamil 31921.180Skamil do { 31931.180Skamil io.piod_addr = (char *)&tcb + bytes_read; 31941.180Skamil io.piod_offs = io.piod_addr; 31951.124Skamil 31961.180Skamil rv = ptrace(PT_IO, child, &io, sizeof(io)); 31971.180Skamil ATF_REQUIRE(rv != -1 && io.piod_len != 0); 31981.31Skamil 31991.180Skamil bytes_read += io.piod_len; 32001.180Skamil io.piod_len = sizeof(tcb) - bytes_read; 32011.180Skamil } while (bytes_read < sizeof(tcb)); 32021.149Skamil 32031.180Skamil for (n = 0; n <= threads; n++) { 32041.180Skamil if (strstr(iter, "LWPINFO") != NULL) { 32051.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 32061.180Skamil "child\n"); 32071.180Skamil SYSCALL_REQUIRE( 32081.180Skamil ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 32091.180Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 32101.149Skamil 32111.180Skamil DPRINTF("Assert that the thread exists\n"); 32121.180Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 32131.149Skamil 32141.180Skamil DPRINTF("Assert that lwp thread %d received expected " 32151.180Skamil "event\n", lwp.pl_lwpid); 32161.180Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 32171.180Skamil info.psi_lwpid == lwp.pl_lwpid ? 32181.180Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 32191.149Skamil 32201.180Skamil if (strstr(iter, "LWPSTATUS") != NULL) { 32211.180Skamil DPRINTF("Before calling ptrace(2) with " 32221.180Skamil "PT_LWPSTATUS for child\n"); 32231.180Skamil lwpstatus.pl_lwpid = lwp.pl_lwpid; 32241.180Skamil SYSCALL_REQUIRE(ptrace(PT_LWPSTATUS, child, 32251.180Skamil &lwpstatus, sizeof(lwpstatus)) != -1); 32261.149Skamil 32271.180Skamil goto check_lwpstatus; 32281.180Skamil } 32291.149Skamil } else { 32301.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for " 32311.180Skamil "child\n"); 32321.180Skamil SYSCALL_REQUIRE( 32331.180Skamil ptrace(PT_LWPNEXT, child, &lwpstatus, 32341.180Skamil sizeof(lwpstatus)) != -1); 32351.180Skamil DPRINTF("LWP=%d\n", lwpstatus.pl_lwpid); 32361.149Skamil 32371.180Skamil DPRINTF("Assert that the thread exists\n"); 32381.180Skamil ATF_REQUIRE(lwpstatus.pl_lwpid > 0); 32391.149Skamil 32401.180Skamil check_lwpstatus: 32411.149Skamil 32421.180Skamil if (strstr(iter, "pl_sigmask") != NULL) { 32431.180Skamil sigmask = lwpstatus.pl_sigmask; 32441.149Skamil 32451.180Skamil DPRINTF("Retrieved sigmask: " 32461.180Skamil "%02x%02x%02x%02x\n", 32471.180Skamil sigmask.__bits[0], sigmask.__bits[1], 32481.180Skamil sigmask.__bits[2], sigmask.__bits[3]); 32491.149Skamil 32501.180Skamil found = false; 32511.180Skamil for (m = 0; 32521.180Skamil m < __arraycount(lwpinfo_thread_sigmask); 32531.180Skamil m++) { 32541.180Skamil if (sigismember(&sigmask, 32551.180Skamil lwpinfo_thread_sigmask[m])) { 32561.180Skamil found = true; 32571.180Skamil lwpinfo_thread_sigmask[m] = 0; 32581.180Skamil break; 32591.180Skamil } 32601.180Skamil } 32611.180Skamil ATF_REQUIRE(found == true); 32621.180Skamil } else if (strstr(iter, "pl_name") != NULL) { 32631.180Skamil name = lwpstatus.pl_name; 32641.149Skamil 32651.180Skamil DPRINTF("Retrieved thread name: " 32661.180Skamil "%s\n", name); 32671.149Skamil 32681.180Skamil snprintf(namebuf, sizeof namebuf, "thread %d", 32691.180Skamil lwpstatus.pl_lwpid); 32701.149Skamil 32711.180Skamil ATF_REQUIRE(strcmp(name, namebuf) == 0); 32721.180Skamil } else if (strstr(iter, "pl_private") != NULL) { 32731.180Skamil private = lwpstatus.pl_private; 32741.149Skamil 32751.180Skamil DPRINTF("Retrieved thread private pointer: " 32761.180Skamil "%p\n", private); 32771.149Skamil 32781.180Skamil found = false; 32791.180Skamil for (m = 0; m < __arraycount(tcb); m++) { 32801.180Skamil DPRINTF("Comparing %p and %p\n", 32811.180Skamil private, tcb[m]); 32821.180Skamil if (private == tcb[m]) { 32831.180Skamil found = true; 32841.180Skamil break; 32851.180Skamil } 32861.180Skamil } 32871.180Skamil ATF_REQUIRE(found == true); 32881.180Skamil } 32891.180Skamil } 32901.180Skamil } 32911.149Skamil 32921.180Skamil if (strstr(iter, "LWPINFO") != NULL) { 32931.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 32941.180Skamil "child\n"); 32951.180Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) 32961.180Skamil != -1); 32971.180Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 32981.149Skamil 32991.180Skamil DPRINTF("Assert that there are no more threads\n"); 33001.180Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 33011.180Skamil } else { 33021.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for child\n"); 33031.180Skamil SYSCALL_REQUIRE(ptrace(PT_LWPNEXT, child, &lwpstatus, 33041.180Skamil sizeof(lwpstatus)) != -1); 33051.149Skamil 33061.180Skamil DPRINTF("Assert that there exists a single thread only\n"); 33071.180Skamil ATF_REQUIRE_EQ(lwpstatus.pl_lwpid, 0); 33081.180Skamil } 33091.149Skamil 33101.180Skamil DPRINTF("Before resuming the child process where it left off and " 33111.180Skamil "without signal to be sent\n"); 33121.180Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1); 33131.149Skamil 33141.180Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 33151.180Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 33161.149Skamil 33171.180Skamil validate_status_signaled(status, SIGKILL, 0); 33181.149Skamil 33191.180Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 33201.180Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 33211.180Skamil} 33221.149Skamil 33231.180Skamil#define TRACEME_LWPINFO(test, threads, iter) \ 33241.180SkamilATF_TC(test); \ 33251.180SkamilATF_TC_HEAD(test, tc) \ 33261.180Skamil{ \ 33271.180Skamil atf_tc_set_md_var(tc, "descr", \ 33281.180Skamil "Verify " iter " with the child with " #threads \ 33291.180Skamil " spawned extra threads"); \ 33301.180Skamil} \ 33311.180Skamil \ 33321.180SkamilATF_TC_BODY(test, tc) \ 33331.180Skamil{ \ 33341.180Skamil \ 33351.180Skamil traceme_lwpinfo(threads, iter); \ 33361.180Skamil} 33371.149Skamil 33381.180SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0, "LWPINFO") 33391.180SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1, "LWPINFO") 33401.180SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2, "LWPINFO") 33411.180SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3, "LWPINFO") 33421.149Skamil 33431.180SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus, 0, "LWPINFO+LWPSTATUS") 33441.180SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus, 1, "LWPINFO+LWPSTATUS") 33451.180SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus, 2, "LWPINFO+LWPSTATUS") 33461.180SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus, 3, "LWPINFO+LWPSTATUS") 33471.149Skamil 33481.180SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus_pl_sigmask, 0, 33491.180Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 33501.180SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus_pl_sigmask, 1, 33511.180Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 33521.180SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus_pl_sigmask, 2, 33531.180Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 33541.180SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus_pl_sigmask, 3, 33551.180Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 33561.149Skamil 33571.180SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus_pl_name, 0, 33581.180Skamil "LWPINFO+LWPSTATUS+pl_name") 33591.180SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus_pl_name, 1, 33601.180Skamil "LWPINFO+LWPSTATUS+pl_name") 33611.180SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus_pl_name, 2, 33621.180Skamil "LWPINFO+LWPSTATUS+pl_name") 33631.180SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus_pl_name, 3, 33641.180Skamil "LWPINFO+LWPSTATUS+pl_name") 33651.149Skamil 33661.180SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus_pl_private, 0, 33671.180Skamil "LWPINFO+LWPSTATUS+pl_private") 33681.180SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus_pl_private, 1, 33691.180Skamil "LWPINFO+LWPSTATUS+pl_private") 33701.180SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus_pl_private, 2, 33711.180Skamil "LWPINFO+LWPSTATUS+pl_private") 33721.180SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus_pl_private, 3, 33731.180Skamil "LWPINFO+LWPSTATUS+pl_private") 33741.149Skamil 33751.180SkamilTRACEME_LWPINFO(traceme_lwpnext0, 0, "LWPNEXT") 33761.180SkamilTRACEME_LWPINFO(traceme_lwpnext1, 1, "LWPNEXT") 33771.180SkamilTRACEME_LWPINFO(traceme_lwpnext2, 2, "LWPNEXT") 33781.180SkamilTRACEME_LWPINFO(traceme_lwpnext3, 3, "LWPNEXT") 33791.149Skamil 33801.180SkamilTRACEME_LWPINFO(traceme_lwpnext0_pl_sigmask, 0, "LWPNEXT+pl_sigmask") 33811.180SkamilTRACEME_LWPINFO(traceme_lwpnext1_pl_sigmask, 1, "LWPNEXT+pl_sigmask") 33821.180SkamilTRACEME_LWPINFO(traceme_lwpnext2_pl_sigmask, 2, "LWPNEXT+pl_sigmask") 33831.180SkamilTRACEME_LWPINFO(traceme_lwpnext3_pl_sigmask, 3, "LWPNEXT+pl_sigmask") 33841.149Skamil 33851.180SkamilTRACEME_LWPINFO(traceme_lwpnext0_pl_name, 0, "LWPNEXT+pl_name") 33861.180SkamilTRACEME_LWPINFO(traceme_lwpnext1_pl_name, 1, "LWPNEXT+pl_name") 33871.180SkamilTRACEME_LWPINFO(traceme_lwpnext2_pl_name, 2, "LWPNEXT+pl_name") 33881.180SkamilTRACEME_LWPINFO(traceme_lwpnext3_pl_name, 3, "LWPNEXT+pl_name") 33891.149Skamil 33901.180SkamilTRACEME_LWPINFO(traceme_lwpnext0_pl_private, 0, "LWPNEXT+pl_private") 33911.180SkamilTRACEME_LWPINFO(traceme_lwpnext1_pl_private, 1, "LWPNEXT+pl_private") 33921.180SkamilTRACEME_LWPINFO(traceme_lwpnext2_pl_private, 2, "LWPNEXT+pl_private") 33931.180SkamilTRACEME_LWPINFO(traceme_lwpnext3_pl_private, 3, "LWPNEXT+pl_private") 33941.149Skamil 33951.180Skamil/// ---------------------------------------------------------------------------- 33961.149Skamil 33971.180Skamil#if defined(TWAIT_HAVE_PID) 33981.180Skamilstatic void 33991.180Skamilattach_lwpinfo(const int threads) 34001.180Skamil{ 34011.180Skamil const int sigval = SIGINT; 34021.180Skamil struct msg_fds parent_tracee, parent_tracer; 34031.180Skamil const int exitval_tracer = 10; 34041.180Skamil pid_t tracee, tracer, wpid; 34051.180Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 34061.180Skamil#if defined(TWAIT_HAVE_STATUS) 34071.180Skamil int status; 34081.180Skamil#endif 34091.180Skamil struct ptrace_lwpinfo lwp = {0, 0}; 34101.180Skamil struct ptrace_siginfo info; 34111.149Skamil 34121.180Skamil /* Maximum number of supported threads in this test */ 34131.180Skamil pthread_t t[3]; 34141.180Skamil int n, rv; 34151.149Skamil 34161.180Skamil DPRINTF("Spawn tracee\n"); 34171.180Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 34181.180Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 34191.180Skamil tracee = atf_utils_fork(); 34201.180Skamil if (tracee == 0) { 34211.180Skamil /* Wait for message from the parent */ 34221.180Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 34231.149Skamil 34241.180Skamil CHILD_FROM_PARENT("spawn threads", parent_tracee, msg); 34251.149Skamil 34261.180Skamil for (n = 0; n < threads; n++) { 34271.180Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 34281.180Skamil FORKEE_ASSERT(rv == 0); 34291.149Skamil } 34301.149Skamil 34311.180Skamil CHILD_TO_PARENT("tracee exit", parent_tracee, msg); 34321.149Skamil 34331.180Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 34341.180Skamil FORKEE_ASSERT(raise(sigval) == 0); 34351.149Skamil 34361.180Skamil /* NOTREACHED */ 34371.180Skamil FORKEE_ASSERTX(0 && "Not reached"); 34381.150Skamil } 34391.180Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 34401.150Skamil 34411.150Skamil DPRINTF("Spawn debugger\n"); 34421.150Skamil tracer = atf_utils_fork(); 34431.150Skamil if (tracer == 0) { 34441.180Skamil /* No IPC to communicate with the child */ 34451.150Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 34461.150Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 34471.150Skamil 34481.150Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 34491.150Skamil FORKEE_REQUIRE_SUCCESS( 34501.150Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 34511.150Skamil 34521.150Skamil forkee_status_stopped(status, SIGSTOP); 34531.150Skamil 34541.180Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 34551.180Skamil "tracee"); 34561.180Skamil FORKEE_ASSERT( 34571.150Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 34581.150Skamil 34591.150Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 34601.150Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 34611.180Skamil "si_errno=%#x\n", 34621.180Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 34631.180Skamil info.psi_siginfo.si_errno); 34641.150Skamil 34651.150Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 34661.150Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 34671.150Skamil 34681.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 34691.180Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 34701.180Skamil != -1); 34711.180Skamil 34721.180Skamil DPRINTF("Assert that there exists a thread\n"); 34731.180Skamil FORKEE_ASSERTX(lwp.pl_lwpid > 0); 34741.180Skamil 34751.180Skamil DPRINTF("Assert that lwp thread %d received event " 34761.180Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 34771.180Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 34781.180Skamil 34791.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 34801.180Skamil "tracee\n"); 34811.180Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 34821.180Skamil != -1); 34831.180Skamil 34841.180Skamil DPRINTF("Assert that there are no more lwp threads in " 34851.180Skamil "tracee\n"); 34861.180Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 34871.180Skamil 34881.150Skamil /* Resume tracee with PT_CONTINUE */ 34891.150Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 34901.150Skamil 34911.150Skamil /* Inform parent that tracer has attached to tracee */ 34921.150Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 34931.150Skamil 34941.180Skamil /* Wait for parent */ 34951.180Skamil CHILD_FROM_PARENT("tracer wait", parent_tracer, msg); 34961.150Skamil 34971.180Skamil /* Wait for tracee and assert that it raised a signal */ 34981.150Skamil FORKEE_REQUIRE_SUCCESS( 34991.150Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 35001.150Skamil 35011.180Skamil forkee_status_stopped(status, SIGINT); 35021.150Skamil 35031.180Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 35041.180Skamil "child"); 35051.180Skamil FORKEE_ASSERT( 35061.150Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 35071.150Skamil 35081.150Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 35091.150Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 35101.180Skamil "si_errno=%#x\n", 35111.180Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 35121.180Skamil info.psi_siginfo.si_errno); 35131.150Skamil 35141.150Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 35151.150Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 35161.150Skamil 35171.180Skamil memset(&lwp, 0, sizeof(lwp)); 35181.150Skamil 35191.180Skamil for (n = 0; n <= threads; n++) { 35201.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 35211.180Skamil "child\n"); 35221.180Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, 35231.180Skamil sizeof(lwp)) != -1); 35241.180Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 35251.150Skamil 35261.180Skamil DPRINTF("Assert that the thread exists\n"); 35271.180Skamil FORKEE_ASSERT(lwp.pl_lwpid > 0); 35281.150Skamil 35291.180Skamil DPRINTF("Assert that lwp thread %d received expected " 35301.180Skamil "event\n", lwp.pl_lwpid); 35311.180Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 35321.180Skamil info.psi_lwpid == lwp.pl_lwpid ? 35331.180Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 35341.180Skamil } 35351.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 35361.180Skamil "tracee\n"); 35371.180Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 35381.180Skamil != -1); 35391.180Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 35401.150Skamil 35411.180Skamil DPRINTF("Assert that there are no more threads\n"); 35421.180Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 35431.150Skamil 35441.180Skamil DPRINTF("Before resuming the child process where it left off " 35451.150Skamil "and without signal to be sent\n"); 35461.180Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL) 35471.180Skamil != -1); 35481.150Skamil 35491.180Skamil /* Wait for tracee and assert that it exited */ 35501.180Skamil FORKEE_REQUIRE_SUCCESS( 35511.180Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 35521.150Skamil 35531.180Skamil forkee_status_signaled(status, SIGKILL, 0); 35541.150Skamil 35551.150Skamil DPRINTF("Before exiting of the tracer process\n"); 35561.180Skamil _exit(exitval_tracer); 35571.97Skamil } 35581.97Skamil 35591.180Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 35601.180Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 35611.97Skamil 35621.180Skamil DPRINTF("Resume the tracee and spawn threads\n"); 35631.180Skamil PARENT_TO_CHILD("spawn threads", parent_tracee, msg); 35641.97Skamil 35651.180Skamil DPRINTF("Resume the tracee and let it exit\n"); 35661.180Skamil PARENT_FROM_CHILD("tracee exit", parent_tracee, msg); 35671.97Skamil 35681.180Skamil DPRINTF("Resume the tracer and let it detect multiple threads\n"); 35691.180Skamil PARENT_TO_CHILD("tracer wait", parent_tracer, msg); 35701.1Skamil 35711.180Skamil DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n", 35721.180Skamil TWAIT_FNAME); 35731.180Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 35741.180Skamil tracer); 35751.1Skamil 35761.180Skamil validate_status_exited(status, exitval_tracer); 35771.1Skamil 35781.180Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 35791.180Skamil TWAIT_FNAME); 35801.180Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 35811.180Skamil tracee); 35821.1Skamil 35831.180Skamil validate_status_signaled(status, SIGKILL, 0); 35841.1Skamil 35851.180Skamil msg_close(&parent_tracer); 35861.180Skamil msg_close(&parent_tracee); 35871.1Skamil} 35881.1Skamil 35891.180Skamil#define ATTACH_LWPINFO(test, threads) \ 35901.97SkamilATF_TC(test); \ 35911.97SkamilATF_TC_HEAD(test, tc) \ 35921.97Skamil{ \ 35931.180Skamil atf_tc_set_md_var(tc, "descr", \ 35941.180Skamil "Verify LWPINFO with the child with " #threads \ 35951.180Skamil " spawned extra threads (tracer is not the original " \ 35961.180Skamil "parent)"); \ 35971.97Skamil} \ 35981.97Skamil \ 35991.97SkamilATF_TC_BODY(test, tc) \ 36001.97Skamil{ \ 36011.97Skamil \ 36021.180Skamil attach_lwpinfo(threads); \ 36031.97Skamil} 36041.97Skamil 36051.180SkamilATTACH_LWPINFO(attach_lwpinfo0, 0) 36061.180SkamilATTACH_LWPINFO(attach_lwpinfo1, 1) 36071.180SkamilATTACH_LWPINFO(attach_lwpinfo2, 2) 36081.180SkamilATTACH_LWPINFO(attach_lwpinfo3, 3) 36091.180Skamil#endif 36101.97Skamil 36111.82Skamil/// ---------------------------------------------------------------------------- 36121.82Skamil 36131.83Skamilstatic void 36141.180Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught) 36151.1Skamil{ 36161.180Skamil const int exitval = 5; 36171.180Skamil const int sigval = SIGINT; 36181.180Skamil const int sigfaked = SIGTRAP; 36191.180Skamil const int sicodefaked = TRAP_BRKPT; 36201.1Skamil pid_t child, wpid; 36211.180Skamil struct sigaction sa; 36221.1Skamil#if defined(TWAIT_HAVE_STATUS) 36231.1Skamil int status; 36241.1Skamil#endif 36251.83Skamil struct ptrace_siginfo info; 36261.180Skamil memset(&info, 0, sizeof(info)); 36271.83Skamil 36281.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 36291.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 36301.1Skamil if (child == 0) { 36311.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 36321.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 36331.1Skamil 36341.180Skamil sa.sa_sigaction = sah; 36351.180Skamil sa.sa_flags = SA_SIGINFO; 36361.180Skamil sigemptyset(&sa.sa_mask); 36371.180Skamil 36381.180Skamil FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL) 36391.180Skamil != -1); 36401.153Skamil 36411.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 36421.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 36431.1Skamil 36441.180Skamil FORKEE_ASSERT_EQ(*signal_caught, 1); 36451.1Skamil 36461.180Skamil DPRINTF("Before exiting of the child process\n"); 36471.180Skamil _exit(exitval); 36481.1Skamil } 36491.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 36501.1Skamil 36511.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 36521.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 36531.1Skamil 36541.1Skamil validate_status_stopped(status, sigval); 36551.1Skamil 36561.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 36571.83Skamil SYSCALL_REQUIRE( 36581.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 36591.1Skamil 36601.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 36611.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 36621.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 36631.83Skamil info.psi_siginfo.si_errno); 36641.1Skamil 36651.180Skamil if (faked) { 36661.180Skamil DPRINTF("Before setting new faked signal to signo=%d " 36671.180Skamil "si_code=%d\n", sigfaked, sicodefaked); 36681.180Skamil info.psi_siginfo.si_signo = sigfaked; 36691.180Skamil info.psi_siginfo.si_code = sicodefaked; 36701.83Skamil } 36711.1Skamil 36721.180Skamil DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n"); 36731.180Skamil SYSCALL_REQUIRE( 36741.180Skamil ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1); 36751.1Skamil 36761.180Skamil if (faked) { 36771.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 36781.83Skamil "child\n"); 36791.180Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 36801.180Skamil sizeof(info)) != -1); 36811.1Skamil 36821.180Skamil DPRINTF("Before checking siginfo_t\n"); 36831.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked); 36841.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked); 36851.83Skamil } 36861.1Skamil 36871.180Skamil DPRINTF("Before resuming the child process where it left off and " 36881.180Skamil "without signal to be sent\n"); 36891.180Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 36901.180Skamil faked ? sigfaked : sigval) != -1); 36911.1Skamil 36921.180Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 36931.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 36941.1Skamil 36951.180Skamil validate_status_exited(status, exitval); 36961.1Skamil 36971.180Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 36981.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 36991.1Skamil} 37001.1Skamil 37011.180Skamil#define PTRACE_SIGINFO(test, faked) \ 37021.83SkamilATF_TC(test); \ 37031.83SkamilATF_TC_HEAD(test, tc) \ 37041.83Skamil{ \ 37051.180Skamil atf_tc_set_md_var(tc, "descr", \ 37061.180Skamil "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls" \ 37071.180Skamil "with%s setting signal to new value", faked ? "" : "out"); \ 37081.180Skamil} \ 37091.180Skamil \ 37101.180Skamilstatic int test##_caught = 0; \ 37111.180Skamil \ 37121.180Skamilstatic void \ 37131.180Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx) \ 37141.180Skamil{ \ 37151.180Skamil if (faked) { \ 37161.180Skamil FORKEE_ASSERT_EQ(sig, SIGTRAP); \ 37171.180Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP); \ 37181.180Skamil FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT); \ 37191.180Skamil } else { \ 37201.180Skamil FORKEE_ASSERT_EQ(sig, SIGINT); \ 37211.180Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGINT); \ 37221.180Skamil FORKEE_ASSERT_EQ(info->si_code, SI_LWP); \ 37231.180Skamil } \ 37241.180Skamil \ 37251.180Skamil ++ test##_caught; \ 37261.83Skamil} \ 37271.83Skamil \ 37281.83SkamilATF_TC_BODY(test, tc) \ 37291.83Skamil{ \ 37301.83Skamil \ 37311.180Skamil ptrace_siginfo(faked, test##_sighandler, & test##_caught); \ 37321.83Skamil} 37331.83Skamil 37341.180SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false) 37351.180SkamilPTRACE_SIGINFO(siginfo_set_faked, true) 37361.83Skamil 37371.83Skamil/// ---------------------------------------------------------------------------- 37381.83Skamil 37391.180Skamilstatic void 37401.180Skamiltraceme_exec(bool masked, bool ignored) 37411.1Skamil{ 37421.180Skamil const int sigval = SIGTRAP; 37431.1Skamil pid_t child, wpid; 37441.1Skamil#if defined(TWAIT_HAVE_STATUS) 37451.1Skamil int status; 37461.1Skamil#endif 37471.180Skamil struct sigaction sa; 37481.180Skamil struct ptrace_siginfo info; 37491.1Skamil sigset_t intmask; 37501.180Skamil struct kinfo_proc2 kp; 37511.180Skamil size_t len = sizeof(kp); 37521.180Skamil 37531.180Skamil int name[6]; 37541.180Skamil const size_t namelen = __arraycount(name); 37551.180Skamil ki_sigset_t kp_sigmask; 37561.180Skamil ki_sigset_t kp_sigignore; 37571.180Skamil 37581.180Skamil memset(&info, 0, sizeof(info)); 37591.1Skamil 37601.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 37611.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 37621.1Skamil if (child == 0) { 37631.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 37641.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 37651.1Skamil 37661.180Skamil if (masked) { 37671.180Skamil sigemptyset(&intmask); 37681.180Skamil sigaddset(&intmask, sigval); 37691.180Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 37701.180Skamil } 37711.1Skamil 37721.180Skamil if (ignored) { 37731.180Skamil memset(&sa, 0, sizeof(sa)); 37741.180Skamil sa.sa_handler = SIG_IGN; 37751.180Skamil sigemptyset(&sa.sa_mask); 37761.180Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 37771.180Skamil } 37781.1Skamil 37791.180Skamil DPRINTF("Before calling execve(2) from child\n"); 37801.180Skamil execlp("/bin/echo", "/bin/echo", NULL); 37811.1Skamil 37821.180Skamil FORKEE_ASSERT(0 && "Not reached"); 37831.1Skamil } 37841.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 37851.1Skamil 37861.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 37871.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 37881.1Skamil 37891.1Skamil validate_status_stopped(status, sigval); 37901.1Skamil 37911.180Skamil name[0] = CTL_KERN, 37921.180Skamil name[1] = KERN_PROC2, 37931.180Skamil name[2] = KERN_PROC_PID; 37941.180Skamil name[3] = getpid(); 37951.180Skamil name[4] = sizeof(kp); 37961.180Skamil name[5] = 1; 37971.180Skamil 37981.180Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 37991.180Skamil 38001.180Skamil if (masked) 38011.180Skamil kp_sigmask = kp.p_sigmask; 38021.180Skamil 38031.180Skamil if (ignored) 38041.180Skamil kp_sigignore = kp.p_sigignore; 38051.180Skamil 38061.180Skamil name[3] = getpid(); 38071.180Skamil 38081.180Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 38091.180Skamil 38101.180Skamil if (masked) { 38111.180Skamil DPRINTF("kp_sigmask=" 38121.180Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 38131.180Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 38141.180Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 38151.180Skamil 38161.180Skamil DPRINTF("kp.p_sigmask=" 38171.180Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 38181.180Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 38191.180Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 38201.180Skamil 38211.180Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 38221.180Skamil sizeof(kp_sigmask))); 38231.180Skamil } 38241.180Skamil 38251.180Skamil if (ignored) { 38261.180Skamil DPRINTF("kp_sigignore=" 38271.180Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 38281.180Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 38291.180Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 38301.180Skamil 38311.180Skamil DPRINTF("kp.p_sigignore=" 38321.180Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 38331.180Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 38341.180Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 38351.180Skamil 38361.180Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 38371.180Skamil sizeof(kp_sigignore))); 38381.180Skamil } 38391.180Skamil 38401.180Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 38411.180Skamil SYSCALL_REQUIRE( 38421.180Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 38431.1Skamil 38441.180Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 38451.180Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 38461.180Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 38471.180Skamil info.psi_siginfo.si_errno); 38481.1Skamil 38491.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 38501.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 38511.1Skamil 38521.13Schristos DPRINTF("Before resuming the child process where it left off and " 38531.1Skamil "without signal to be sent\n"); 38541.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 38551.1Skamil 38561.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38571.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 38581.1Skamil 38591.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 38601.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 38611.1Skamil} 38621.1Skamil 38631.180Skamil#define TRACEME_EXEC(test, masked, ignored) \ 38641.180SkamilATF_TC(test); \ 38651.180SkamilATF_TC_HEAD(test, tc) \ 38661.180Skamil{ \ 38671.180Skamil atf_tc_set_md_var(tc, "descr", \ 38681.180Skamil "Detect SIGTRAP TRAP_EXEC from " \ 38691.180Skamil "child%s%s", masked ? " with masked signal" : "", \ 38701.180Skamil masked ? " with ignored signal" : ""); \ 38711.180Skamil} \ 38721.180Skamil \ 38731.180SkamilATF_TC_BODY(test, tc) \ 38741.180Skamil{ \ 38751.180Skamil \ 38761.180Skamil traceme_exec(masked, ignored); \ 38771.180Skamil} 38781.180Skamil 38791.180SkamilTRACEME_EXEC(traceme_exec, false, false) 38801.180SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false) 38811.180SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true) 38821.180Skamil 38831.84Skamil/// ---------------------------------------------------------------------------- 38841.84Skamil 38851.180Skamil#define TRACE_THREADS_NUM 100 38861.180Skamil 38871.180Skamilstatic volatile int done; 38881.180Skamilpthread_mutex_t trace_threads_mtx = PTHREAD_MUTEX_INITIALIZER; 38891.180Skamil 38901.180Skamilstatic void * 38911.180Skamiltrace_threads_cb(void *arg __unused) 38921.180Skamil{ 38931.180Skamil 38941.180Skamil pthread_mutex_lock(&trace_threads_mtx); 38951.180Skamil done++; 38961.180Skamil pthread_mutex_unlock(&trace_threads_mtx); 38971.180Skamil 38981.180Skamil while (done < TRACE_THREADS_NUM) 38991.180Skamil sched_yield(); 39001.180Skamil 39011.180Skamil return NULL; 39021.180Skamil} 39031.180Skamil 39041.99Skamilstatic void 39051.180Skamiltrace_threads(bool trace_create, bool trace_exit, bool masked) 39061.1Skamil{ 39071.1Skamil const int sigval = SIGSTOP; 39081.180Skamil pid_t child, wpid; 39091.1Skamil#if defined(TWAIT_HAVE_STATUS) 39101.1Skamil int status; 39111.1Skamil#endif 39121.1Skamil ptrace_state_t state; 39131.1Skamil const int slen = sizeof(state); 39141.1Skamil ptrace_event_t event; 39151.1Skamil const int elen = sizeof(event); 39161.99Skamil struct ptrace_siginfo info; 39171.180Skamil 39181.99Skamil sigset_t intmask; 39191.99Skamil 39201.180Skamil pthread_t t[TRACE_THREADS_NUM]; 39211.180Skamil int rv; 39221.180Skamil size_t n; 39231.180Skamil lwpid_t lid; 39241.1Skamil 39251.180Skamil /* Track created and exited threads */ 39261.180Skamil struct lwp_event_count traced_lwps[__arraycount(t)] = {{0, 0}}; 39271.14Schristos 39281.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 39291.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 39301.1Skamil if (child == 0) { 39311.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 39321.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 39331.1Skamil 39341.99Skamil if (masked) { 39351.99Skamil sigemptyset(&intmask); 39361.99Skamil sigaddset(&intmask, SIGTRAP); 39371.99Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 39381.99Skamil } 39391.99Skamil 39401.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 39411.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 39421.1Skamil 39431.180Skamil for (n = 0; n < __arraycount(t); n++) { 39441.180Skamil rv = pthread_create(&t[n], NULL, trace_threads_cb, 39451.180Skamil NULL); 39461.180Skamil FORKEE_ASSERT(rv == 0); 39471.126Skamil } 39481.1Skamil 39491.180Skamil for (n = 0; n < __arraycount(t); n++) { 39501.180Skamil rv = pthread_join(t[n], NULL); 39511.180Skamil FORKEE_ASSERT(rv == 0); 39521.180Skamil } 39531.1Skamil 39541.180Skamil /* 39551.180Skamil * There is race between _exit() and pthread_join() detaching 39561.180Skamil * a thread. For simplicity kill the process after detecting 39571.180Skamil * LWP events. 39581.180Skamil */ 39591.180Skamil while (true) 39601.180Skamil continue; 39611.1Skamil 39621.180Skamil FORKEE_ASSERT(0 && "Not reached"); 39631.1Skamil } 39641.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 39651.1Skamil 39661.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 39671.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 39681.1Skamil 39691.1Skamil validate_status_stopped(status, sigval); 39701.1Skamil 39711.99Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 39721.99Skamil SYSCALL_REQUIRE( 39731.99Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 39741.99Skamil 39751.180Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 39761.180Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 39771.180Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 39781.180Skamil info.psi_siginfo.si_errno); 39791.180Skamil 39801.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 39811.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 39821.1Skamil 39831.180Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 39841.180Skamil memset(&event, 0, sizeof(event)); 39851.180Skamil if (trace_create) 39861.180Skamil event.pe_set_event |= PTRACE_LWP_CREATE; 39871.180Skamil if (trace_exit) 39881.180Skamil event.pe_set_event |= PTRACE_LWP_EXIT; 39891.99Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 39901.1Skamil 39911.99Skamil DPRINTF("Before resuming the child process where it left off and " 39921.99Skamil "without signal to be sent\n"); 39931.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 39941.1Skamil 39951.180Skamil for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) { 39961.180Skamil DPRINTF("Before calling %s() for the child - expected stopped " 39971.180Skamil "SIGTRAP\n", TWAIT_FNAME); 39981.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 39991.99Skamil child); 40001.1Skamil 40011.99Skamil validate_status_stopped(status, SIGTRAP); 40021.1Skamil 40031.180Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 40041.180Skamil "child\n"); 40051.180Skamil SYSCALL_REQUIRE( 40061.180Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 40071.180Skamil 40081.180Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 40091.180Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 40101.180Skamil "si_errno=%#x\n", 40111.180Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 40121.180Skamil info.psi_siginfo.si_errno); 40131.1Skamil 40141.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 40151.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 40161.1Skamil 40171.180Skamil SYSCALL_REQUIRE( 40181.180Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 40191.1Skamil 40201.180Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 40211.180Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 40221.1Skamil 40231.180Skamil lid = state.pe_lwp; 40241.180Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 40251.1Skamil 40261.180Skamil *FIND_EVENT_COUNT(traced_lwps, lid) += 1; 40271.1Skamil 40281.180Skamil DPRINTF("Before resuming the child process where it left off " 40291.180Skamil "and without signal to be sent\n"); 40301.180Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 40311.180Skamil } 40321.1Skamil 40331.180Skamil for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) { 40341.180Skamil DPRINTF("Before calling %s() for the child - expected stopped " 40351.180Skamil "SIGTRAP\n", TWAIT_FNAME); 40361.180Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 40371.180Skamil child); 40381.1Skamil 40391.99Skamil validate_status_stopped(status, SIGTRAP); 40401.1Skamil 40411.180Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 40421.180Skamil "child\n"); 40431.180Skamil SYSCALL_REQUIRE( 40441.180Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 40451.1Skamil 40461.180Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 40471.180Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 40481.180Skamil "si_errno=%#x\n", 40491.180Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 40501.180Skamil info.psi_siginfo.si_errno); 40511.1Skamil 40521.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 40531.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 40541.14Schristos 40551.180Skamil SYSCALL_REQUIRE( 40561.180Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 40571.1Skamil 40581.180Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 40591.180Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 40601.1Skamil 40611.180Skamil lid = state.pe_lwp; 40621.180Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 40631.1Skamil 40641.180Skamil if (trace_create) { 40651.180Skamil int *count = FIND_EVENT_COUNT(traced_lwps, lid); 40661.180Skamil ATF_REQUIRE_EQ(*count, 1); 40671.180Skamil *count = 0; 40681.99Skamil } 40691.1Skamil 40701.99Skamil DPRINTF("Before resuming the child process where it left off " 40711.99Skamil "and without signal to be sent\n"); 40721.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 40731.1Skamil } 40741.1Skamil 40751.180Skamil kill(child, SIGKILL); 40761.180Skamil 40771.180Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 40781.180Skamil TWAIT_FNAME); 40791.180Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 40801.180Skamil 40811.180Skamil validate_status_signaled(status, SIGKILL, 0); 40821.1Skamil 40831.180Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 40841.180Skamil TWAIT_FNAME); 40851.180Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 40861.180Skamil} 40871.1Skamil 40881.180Skamil#define TRACE_THREADS(test, trace_create, trace_exit, mask) \ 40891.180SkamilATF_TC(test); \ 40901.180SkamilATF_TC_HEAD(test, tc) \ 40911.180Skamil{ \ 40921.180Skamil atf_tc_set_md_var(tc, "descr", \ 40931.180Skamil "Verify spawning threads with%s tracing LWP create and" \ 40941.180Skamil "with%s tracing LWP exit", trace_create ? "" : "out", \ 40951.180Skamil trace_exit ? "" : "out"); \ 40961.180Skamil} \ 40971.180Skamil \ 40981.180SkamilATF_TC_BODY(test, tc) \ 40991.180Skamil{ \ 41001.180Skamil \ 41011.180Skamil trace_threads(trace_create, trace_exit, mask); \ 41021.180Skamil} 41031.1Skamil 41041.180SkamilTRACE_THREADS(trace_thread_nolwpevents, false, false, false) 41051.180SkamilTRACE_THREADS(trace_thread_lwpexit, false, true, false) 41061.180SkamilTRACE_THREADS(trace_thread_lwpcreate, true, false, false) 41071.180SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true, false) 41081.102Skamil 41091.180SkamilTRACE_THREADS(trace_thread_lwpexit_masked_sigtrap, false, true, true) 41101.180SkamilTRACE_THREADS(trace_thread_lwpcreate_masked_sigtrap, true, false, true) 41111.180SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit_masked_sigtrap, true, true, true) 41121.1Skamil 41131.180Skamil/// ---------------------------------------------------------------------------- 41141.1Skamil 41151.180SkamilATF_TC(signal_mask_unrelated); 41161.180SkamilATF_TC_HEAD(signal_mask_unrelated, tc) 41171.180Skamil{ 41181.180Skamil atf_tc_set_md_var(tc, "descr", 41191.180Skamil "Verify that masking single unrelated signal does not stop tracer " 41201.180Skamil "from catching other signals"); 41211.180Skamil} 41221.1Skamil 41231.180SkamilATF_TC_BODY(signal_mask_unrelated, tc) 41241.180Skamil{ 41251.180Skamil const int exitval = 5; 41261.180Skamil const int sigval = SIGSTOP; 41271.180Skamil const int sigmasked = SIGTRAP; 41281.180Skamil const int signotmasked = SIGINT; 41291.180Skamil pid_t child, wpid; 41301.180Skamil#if defined(TWAIT_HAVE_STATUS) 41311.180Skamil int status; 41321.180Skamil#endif 41331.180Skamil sigset_t intmask; 41341.1Skamil 41351.180Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 41361.180Skamil SYSCALL_REQUIRE((child = fork()) != -1); 41371.180Skamil if (child == 0) { 41381.180Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 41391.180Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 41401.1Skamil 41411.180Skamil sigemptyset(&intmask); 41421.180Skamil sigaddset(&intmask, sigmasked); 41431.180Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 41441.1Skamil 41451.180Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 41461.180Skamil FORKEE_ASSERT(raise(sigval) == 0); 41471.1Skamil 41481.180Skamil DPRINTF("Before raising %s from child\n", 41491.180Skamil strsignal(signotmasked)); 41501.180Skamil FORKEE_ASSERT(raise(signotmasked) == 0); 41511.1Skamil 41521.180Skamil DPRINTF("Before exiting of the child process\n"); 41531.180Skamil _exit(exitval); 41541.99Skamil } 41551.180Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 41561.1Skamil 41571.180Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41581.180Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 41591.1Skamil 41601.180Skamil validate_status_stopped(status, sigval); 41611.1Skamil 41621.180Skamil DPRINTF("Before resuming the child process where it left off and " 41631.180Skamil "without signal to be sent\n"); 41641.180Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 41651.1Skamil 41661.180Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41671.57Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 41681.1Skamil 41691.180Skamil validate_status_stopped(status, signotmasked); 41701.1Skamil 41711.57Skamil DPRINTF("Before resuming the child process where it left off and " 41721.1Skamil "without signal to be sent\n"); 41731.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 41741.1Skamil 41751.180Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41761.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 41771.1Skamil 41781.1Skamil validate_status_exited(status, exitval); 41791.1Skamil 41801.180Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 41811.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 41821.1Skamil} 41831.1Skamil 41841.99Skamil/// ---------------------------------------------------------------------------- 41851.1Skamil 41861.151Skamilstatic void * 41871.151Skamilthread_and_exec_thread_cb(void *arg __unused) 41881.151Skamil{ 41891.151Skamil 41901.151Skamil execlp("/bin/echo", "/bin/echo", NULL); 41911.151Skamil 41921.151Skamil abort(); 41931.151Skamil} 41941.151Skamil 41951.151Skamilstatic void 41961.151Skamilthreads_and_exec(void) 41971.151Skamil{ 41981.151Skamil const int sigval = SIGSTOP; 41991.151Skamil pid_t child, wpid; 42001.151Skamil#if defined(TWAIT_HAVE_STATUS) 42011.151Skamil int status; 42021.151Skamil#endif 42031.151Skamil ptrace_state_t state; 42041.151Skamil const int slen = sizeof(state); 42051.151Skamil ptrace_event_t event; 42061.151Skamil const int elen = sizeof(event); 42071.151Skamil struct ptrace_siginfo info; 42081.151Skamil 42091.151Skamil pthread_t t; 42101.151Skamil lwpid_t lid; 42111.151Skamil 42121.151Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 42131.151Skamil SYSCALL_REQUIRE((child = fork()) != -1); 42141.151Skamil if (child == 0) { 42151.151Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 42161.151Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 42171.151Skamil 42181.151Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 42191.151Skamil FORKEE_ASSERT(raise(sigval) == 0); 42201.151Skamil 42211.151Skamil FORKEE_ASSERT(pthread_create(&t, NULL, 42221.151Skamil thread_and_exec_thread_cb, NULL) == 0); 42231.151Skamil 42241.151Skamil for (;;) 42251.151Skamil continue; 42261.151Skamil 42271.151Skamil FORKEE_ASSERT(0 && "Not reached"); 42281.151Skamil } 42291.151Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 42301.151Skamil 42311.151Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 42321.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 42331.151Skamil 42341.151Skamil validate_status_stopped(status, sigval); 42351.151Skamil 42361.151Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 42371.151Skamil SYSCALL_REQUIRE( 42381.151Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 42391.151Skamil 42401.151Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 42411.151Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 42421.151Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 42431.151Skamil info.psi_siginfo.si_errno); 42441.151Skamil 42451.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 42461.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 42471.151Skamil 42481.151Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 42491.151Skamil memset(&event, 0, sizeof(event)); 42501.151Skamil event.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT; 42511.151Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 42521.151Skamil 42531.151Skamil DPRINTF("Before resuming the child process where it left off and " 42541.151Skamil "without signal to be sent\n"); 42551.151Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 42561.151Skamil 42571.151Skamil DPRINTF("Before calling %s() for the child - expected stopped " 42581.151Skamil "SIGTRAP\n", TWAIT_FNAME); 42591.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 42601.151Skamil child); 42611.151Skamil 42621.151Skamil validate_status_stopped(status, SIGTRAP); 42631.151Skamil 42641.151Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 42651.151Skamil "child\n"); 42661.151Skamil SYSCALL_REQUIRE( 42671.151Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 42681.151Skamil 42691.151Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 42701.151Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 42711.151Skamil "si_errno=%#x\n", 42721.151Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 42731.151Skamil info.psi_siginfo.si_errno); 42741.151Skamil 42751.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 42761.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 42771.151Skamil 42781.151Skamil SYSCALL_REQUIRE( 42791.151Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 42801.151Skamil 42811.151Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 42821.151Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 42831.151Skamil 42841.151Skamil lid = state.pe_lwp; 42851.151Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 42861.151Skamil 42871.151Skamil DPRINTF("Before resuming the child process where it left off " 42881.151Skamil "and without signal to be sent\n"); 42891.151Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 42901.151Skamil 42911.151Skamil DPRINTF("Before calling %s() for the child - expected stopped " 42921.151Skamil "SIGTRAP\n", TWAIT_FNAME); 42931.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 42941.151Skamil child); 42951.151Skamil 42961.151Skamil validate_status_stopped(status, SIGTRAP); 42971.151Skamil 42981.151Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 42991.151Skamil "child\n"); 43001.151Skamil SYSCALL_REQUIRE( 43011.151Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 43021.151Skamil 43031.151Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 43041.151Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 43051.151Skamil "si_errno=%#x\n", 43061.151Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 43071.151Skamil info.psi_siginfo.si_errno); 43081.151Skamil 43091.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 43101.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 43111.151Skamil 43121.151Skamil SYSCALL_REQUIRE( 43131.151Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 43141.151Skamil 43151.151Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 43161.151Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 43171.151Skamil 43181.151Skamil lid = state.pe_lwp; 43191.151Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 43201.151Skamil 43211.151Skamil DPRINTF("Before resuming the child process where it left off " 43221.151Skamil "and without signal to be sent\n"); 43231.151Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 43241.151Skamil 43251.151Skamil DPRINTF("Before calling %s() for the child - expected stopped " 43261.151Skamil "SIGTRAP\n", TWAIT_FNAME); 43271.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 43281.151Skamil child); 43291.151Skamil 43301.151Skamil validate_status_stopped(status, SIGTRAP); 43311.151Skamil 43321.151Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 43331.151Skamil "child\n"); 43341.151Skamil SYSCALL_REQUIRE( 43351.151Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 43361.151Skamil 43371.151Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 43381.151Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 43391.151Skamil "si_errno=%#x\n", 43401.151Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 43411.151Skamil info.psi_siginfo.si_errno); 43421.151Skamil 43431.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 43441.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 43451.151Skamil 43461.151Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 43471.151Skamil 43481.151Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 43491.151Skamil TWAIT_FNAME); 43501.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 43511.151Skamil 43521.151Skamil validate_status_signaled(status, SIGKILL, 0); 43531.151Skamil 43541.151Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 43551.151Skamil TWAIT_FNAME); 43561.151Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 43571.151Skamil} 43581.151Skamil 43591.151SkamilATF_TC(threads_and_exec); 43601.151SkamilATF_TC_HEAD(threads_and_exec, tc) 43611.151Skamil{ 43621.151Skamil atf_tc_set_md_var(tc, "descr", 43631.151Skamil "Verify that multithreaded application on exec() will report " 43641.151Skamil "LWP_EXIT events"); 43651.151Skamil} 43661.151Skamil 43671.151SkamilATF_TC_BODY(threads_and_exec, tc) 43681.151Skamil{ 43691.151Skamil 43701.151Skamil threads_and_exec(); 43711.151Skamil} 43721.151Skamil 43731.151Skamil/// ---------------------------------------------------------------------------- 43741.151Skamil 43751.154SkamilATF_TC(suspend_no_deadlock); 43761.154SkamilATF_TC_HEAD(suspend_no_deadlock, tc) 43771.1Skamil{ 43781.1Skamil atf_tc_set_md_var(tc, "descr", 43791.1Skamil "Verify that the while the only thread within a process is " 43801.1Skamil "suspended, the whole process cannot be unstopped"); 43811.1Skamil} 43821.1Skamil 43831.154SkamilATF_TC_BODY(suspend_no_deadlock, tc) 43841.1Skamil{ 43851.1Skamil const int exitval = 5; 43861.1Skamil const int sigval = SIGSTOP; 43871.1Skamil pid_t child, wpid; 43881.1Skamil#if defined(TWAIT_HAVE_STATUS) 43891.1Skamil int status; 43901.1Skamil#endif 43911.1Skamil struct ptrace_siginfo psi; 43921.1Skamil 43931.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 43941.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 43951.1Skamil if (child == 0) { 43961.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 43971.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 43981.1Skamil 43991.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 44001.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 44011.1Skamil 44021.13Schristos DPRINTF("Before exiting of the child process\n"); 44031.1Skamil _exit(exitval); 44041.1Skamil } 44051.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 44061.1Skamil 44071.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 44081.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44091.1Skamil 44101.1Skamil validate_status_stopped(status, sigval); 44111.1Skamil 44121.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 44131.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 44141.1Skamil 44151.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 44161.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 44171.1Skamil 44181.13Schristos DPRINTF("Before resuming the child process where it left off and " 44191.1Skamil "without signal to be sent\n"); 44201.1Skamil ATF_REQUIRE_ERRNO(EDEADLK, 44211.1Skamil ptrace(PT_CONTINUE, child, (void *)1, 0) == -1); 44221.1Skamil 44231.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 44241.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 44251.1Skamil 44261.13Schristos DPRINTF("Before resuming the child process where it left off and " 44271.1Skamil "without signal to be sent\n"); 44281.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 44291.1Skamil 44301.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 44311.1Skamil TWAIT_FNAME); 44321.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 44331.1Skamil 44341.1Skamil validate_status_exited(status, exitval); 44351.1Skamil 44361.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 44371.1Skamil TWAIT_FNAME); 44381.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 44391.1Skamil} 44401.1Skamil 44411.154Skamil/// ---------------------------------------------------------------------------- 44421.154Skamil 44431.155Skamilstatic pthread_barrier_t barrier1_resume; 44441.155Skamilstatic pthread_barrier_t barrier2_resume; 44451.154Skamil 44461.155Skamilstatic void * 44471.155Skamilresume_thread(void *arg) 44481.154Skamil{ 44491.154Skamil 44501.155Skamil raise(SIGUSR1); 44511.155Skamil 44521.155Skamil pthread_barrier_wait(&barrier1_resume); 44531.155Skamil 44541.155Skamil /* Debugger will suspend the process here */ 44551.155Skamil 44561.155Skamil pthread_barrier_wait(&barrier2_resume); 44571.154Skamil 44581.155Skamil raise(SIGUSR2); 44591.155Skamil 44601.155Skamil return infinite_thread(arg); 44611.154Skamil} 44621.154Skamil 44631.155SkamilATF_TC(resume); 44641.155SkamilATF_TC_HEAD(resume, tc) 44651.1Skamil{ 44661.1Skamil atf_tc_set_md_var(tc, "descr", 44671.1Skamil "Verify that a thread can be suspended by a debugger and later " 44681.1Skamil "resumed by the debugger"); 44691.1Skamil} 44701.1Skamil 44711.155SkamilATF_TC_BODY(resume, tc) 44721.1Skamil{ 44731.1Skamil const int sigval = SIGSTOP; 44741.1Skamil pid_t child, wpid; 44751.1Skamil#if defined(TWAIT_HAVE_STATUS) 44761.1Skamil int status; 44771.1Skamil#endif 44781.1Skamil lwpid_t lid; 44791.1Skamil struct ptrace_siginfo psi; 44801.155Skamil pthread_t t; 44811.1Skamil 44821.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 44831.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 44841.1Skamil if (child == 0) { 44851.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 44861.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 44871.1Skamil 44881.155Skamil pthread_barrier_init(&barrier1_resume, NULL, 2); 44891.155Skamil pthread_barrier_init(&barrier2_resume, NULL, 2); 44901.155Skamil 44911.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 44921.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 44931.1Skamil 44941.155Skamil DPRINTF("Before creating new thread in child\n"); 44951.155Skamil FORKEE_ASSERT(pthread_create(&t, NULL, resume_thread, NULL) == 0); 44961.1Skamil 44971.155Skamil pthread_barrier_wait(&barrier1_resume); 44981.1Skamil 44991.155Skamil pthread_barrier_wait(&barrier2_resume); 45001.1Skamil 45011.155Skamil infinite_thread(NULL); 45021.1Skamil } 45031.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 45041.1Skamil 45051.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 45061.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 45071.1Skamil 45081.1Skamil validate_status_stopped(status, sigval); 45091.1Skamil 45101.13Schristos DPRINTF("Before resuming the child process where it left off and " 45111.1Skamil "without signal to be sent\n"); 45121.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 45131.1Skamil 45141.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 45151.155Skamil "SIGUSR1\n", TWAIT_FNAME); 45161.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 45171.1Skamil 45181.155Skamil validate_status_stopped(status, SIGUSR1); 45191.1Skamil 45201.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 45211.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 45221.1Skamil 45231.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 45241.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 45251.1Skamil 45261.155Skamil lid = psi.psi_lwpid; 45271.1Skamil 45281.13Schristos DPRINTF("Before resuming the child process where it left off and " 45291.1Skamil "without signal to be sent\n"); 45301.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 45311.1Skamil 45321.155Skamil DPRINTF("Before suspending the parent for 1 second, we expect no signals\n"); 45331.155Skamil SYSCALL_REQUIRE(sleep(1) == 0); 45341.155Skamil 45351.155Skamil#if defined(TWAIT_HAVE_OPTIONS) 45361.155Skamil DPRINTF("Before calling %s() for the child - expected no status\n", 45371.155Skamil TWAIT_FNAME); 45381.155Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, WNOHANG), 0); 45391.155Skamil#endif 45401.155Skamil 45411.155Skamil DPRINTF("Before resuming the child process where it left off and " 45421.155Skamil "without signal to be sent\n"); 45431.155Skamil SYSCALL_REQUIRE(ptrace(PT_STOP, child, NULL, 0) != -1); 45441.155Skamil 45451.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 45461.155Skamil "SIGSTOP\n", TWAIT_FNAME); 45471.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 45481.1Skamil 45491.155Skamil validate_status_stopped(status, SIGSTOP); 45501.1Skamil 45511.155Skamil DPRINTF("Before resuming LWP %d\n", lid); 45521.155Skamil SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, lid) != -1); 45531.155Skamil 45541.155Skamil DPRINTF("Before resuming the child process where it left off and " 45551.155Skamil "without signal to be sent\n"); 45561.155Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 45571.1Skamil 45581.155Skamil DPRINTF("Before calling %s() for the child - expected stopped " 45591.155Skamil "SIGUSR2\n", TWAIT_FNAME); 45601.155Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 45611.1Skamil 45621.155Skamil validate_status_stopped(status, SIGUSR2); 45631.1Skamil 45641.13Schristos DPRINTF("Before resuming the child process where it left off and " 45651.1Skamil "without signal to be sent\n"); 45661.155Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1); 45671.1Skamil 45681.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 45691.1Skamil TWAIT_FNAME); 45701.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 45711.1Skamil 45721.155Skamil validate_status_signaled(status, SIGKILL, 0); 45731.1Skamil 45741.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 45751.1Skamil TWAIT_FNAME); 45761.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 45771.155Skamil} 45781.1Skamil 45791.155Skamil/// ---------------------------------------------------------------------------- 45801.1Skamil 45811.106Skamilstatic void 45821.122Skamiluser_va0_disable(int operation) 45831.122Skamil{ 45841.122Skamil pid_t child, wpid; 45851.122Skamil#if defined(TWAIT_HAVE_STATUS) 45861.122Skamil int status; 45871.122Skamil#endif 45881.122Skamil const int sigval = SIGSTOP; 45891.122Skamil int rv; 45901.122Skamil 45911.122Skamil struct ptrace_siginfo info; 45921.122Skamil 45931.122Skamil if (get_user_va0_disable() == 0) 45941.122Skamil atf_tc_skip("vm.user_va0_disable is set to 0"); 45951.122Skamil 45961.122Skamil memset(&info, 0, sizeof(info)); 45971.122Skamil 45981.122Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 45991.122Skamil SYSCALL_REQUIRE((child = fork()) != -1); 46001.122Skamil if (child == 0) { 46011.122Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 46021.122Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 46031.122Skamil 46041.122Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 46051.122Skamil FORKEE_ASSERT(raise(sigval) == 0); 46061.122Skamil 46071.122Skamil /* NOTREACHED */ 46081.122Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 46091.122Skamil __unreachable(); 46101.122Skamil } 46111.122Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 46121.122Skamil 46131.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46141.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 46151.122Skamil 46161.122Skamil validate_status_stopped(status, sigval); 46171.122Skamil 46181.122Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 46191.122Skamil "child\n"); 46201.122Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 46211.122Skamil sizeof(info)) != -1); 46221.122Skamil 46231.122Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 46241.122Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 46251.122Skamil "si_errno=%#x\n", 46261.122Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 46271.122Skamil info.psi_siginfo.si_errno); 46281.122Skamil 46291.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 46301.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 46311.122Skamil 46321.122Skamil DPRINTF("Before resuming the child process in PC=0x0 " 46331.122Skamil "and without signal to be sent\n"); 46341.122Skamil errno = 0; 46351.122Skamil rv = ptrace(operation, child, (void *)0, 0); 46361.122Skamil ATF_REQUIRE_EQ(errno, EINVAL); 46371.122Skamil ATF_REQUIRE_EQ(rv, -1); 46381.122Skamil 46391.122Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 46401.122Skamil 46411.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46421.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 46431.122Skamil validate_status_signaled(status, SIGKILL, 0); 46441.122Skamil 46451.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 46461.122Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 46471.122Skamil} 46481.122Skamil 46491.122Skamil#define USER_VA0_DISABLE(test, operation) \ 46501.122SkamilATF_TC(test); \ 46511.122SkamilATF_TC_HEAD(test, tc) \ 46521.122Skamil{ \ 46531.122Skamil atf_tc_set_md_var(tc, "descr", \ 46541.122Skamil "Verify behavior of " #operation " with PC set to 0x0"); \ 46551.122Skamil} \ 46561.122Skamil \ 46571.122SkamilATF_TC_BODY(test, tc) \ 46581.122Skamil{ \ 46591.122Skamil \ 46601.122Skamil user_va0_disable(operation); \ 46611.122Skamil} 46621.122Skamil 46631.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE) 46641.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL) 46651.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH) 46661.122Skamil 46671.122Skamil/// ---------------------------------------------------------------------------- 46681.122Skamil 46691.130Smgorny/* 46701.130Smgorny * Parse the core file and find the requested note. If the reading or parsing 46711.130Smgorny * fails, the test is failed. If the note is found, it is read onto buf, up to 46721.130Smgorny * buf_len. The actual length of the note is returned (which can be greater 46731.130Smgorny * than buf_len, indicating that it has been truncated). If the note is not 46741.130Smgorny * found, -1 is returned. 46751.172Sthorpej * 46761.172Sthorpej * If the note_name ends in '*', then we find the first note that matches 46771.172Sthorpej * the note_name prefix up to the '*' character, e.g.: 46781.172Sthorpej * 46791.172Sthorpej * NetBSD-CORE@* 46801.172Sthorpej * 46811.172Sthorpej * finds the first note whose name prefix matches "NetBSD-CORE@". 46821.130Smgorny */ 46831.130Smgornystatic ssize_t core_find_note(const char *core_path, 46841.130Smgorny const char *note_name, uint64_t note_type, void *buf, size_t buf_len) 46851.130Smgorny{ 46861.130Smgorny int core_fd; 46871.130Smgorny Elf *core_elf; 46881.130Smgorny size_t core_numhdr, i; 46891.130Smgorny ssize_t ret = -1; 46901.172Sthorpej size_t name_len = strlen(note_name); 46911.172Sthorpej bool prefix_match = false; 46921.172Sthorpej 46931.172Sthorpej if (note_name[name_len - 1] == '*') { 46941.172Sthorpej prefix_match = true; 46951.172Sthorpej name_len--; 46961.172Sthorpej } else { 46971.172Sthorpej /* note: we assume note name will be null-terminated */ 46981.172Sthorpej name_len++; 46991.172Sthorpej } 47001.130Smgorny 47011.130Smgorny SYSCALL_REQUIRE((core_fd = open(core_path, O_RDONLY)) != -1); 47021.130Smgorny SYSCALL_REQUIRE(elf_version(EV_CURRENT) != EV_NONE); 47031.130Smgorny SYSCALL_REQUIRE((core_elf = elf_begin(core_fd, ELF_C_READ, NULL))); 47041.130Smgorny 47051.130Smgorny SYSCALL_REQUIRE(elf_getphnum(core_elf, &core_numhdr) != 0); 47061.130Smgorny for (i = 0; i < core_numhdr && ret == -1; i++) { 47071.130Smgorny GElf_Phdr core_hdr; 47081.130Smgorny size_t offset; 47091.130Smgorny SYSCALL_REQUIRE(gelf_getphdr(core_elf, i, &core_hdr)); 47101.130Smgorny if (core_hdr.p_type != PT_NOTE) 47111.130Smgorny continue; 47121.130Smgorny 47131.130Smgorny for (offset = core_hdr.p_offset; 47141.130Smgorny offset < core_hdr.p_offset + core_hdr.p_filesz;) { 47151.130Smgorny Elf64_Nhdr note_hdr; 47161.130Smgorny char name_buf[64]; 47171.130Smgorny 47181.130Smgorny switch (gelf_getclass(core_elf)) { 47191.130Smgorny case ELFCLASS64: 47201.130Smgorny SYSCALL_REQUIRE(pread(core_fd, ¬e_hdr, 47211.130Smgorny sizeof(note_hdr), offset) 47221.130Smgorny == sizeof(note_hdr)); 47231.130Smgorny offset += sizeof(note_hdr); 47241.130Smgorny break; 47251.130Smgorny case ELFCLASS32: 47261.130Smgorny { 47271.130Smgorny Elf32_Nhdr tmp_hdr; 47281.130Smgorny SYSCALL_REQUIRE(pread(core_fd, &tmp_hdr, 47291.130Smgorny sizeof(tmp_hdr), offset) 47301.130Smgorny == sizeof(tmp_hdr)); 47311.130Smgorny offset += sizeof(tmp_hdr); 47321.130Smgorny note_hdr.n_namesz = tmp_hdr.n_namesz; 47331.130Smgorny note_hdr.n_descsz = tmp_hdr.n_descsz; 47341.130Smgorny note_hdr.n_type = tmp_hdr.n_type; 47351.130Smgorny } 47361.130Smgorny break; 47371.130Smgorny } 47381.130Smgorny 47391.130Smgorny /* indicates end of notes */ 47401.130Smgorny if (note_hdr.n_namesz == 0 || note_hdr.n_descsz == 0) 47411.130Smgorny break; 47421.172Sthorpej if (((prefix_match && 47431.172Sthorpej note_hdr.n_namesz > name_len) || 47441.172Sthorpej (!prefix_match && 47451.172Sthorpej note_hdr.n_namesz == name_len)) && 47461.130Smgorny note_hdr.n_namesz <= sizeof(name_buf)) { 47471.130Smgorny SYSCALL_REQUIRE(pread(core_fd, name_buf, 47481.130Smgorny note_hdr.n_namesz, offset) 47491.131Skamil == (ssize_t)(size_t)note_hdr.n_namesz); 47501.130Smgorny 47511.130Smgorny if (!strncmp(note_name, name_buf, name_len) && 47521.130Smgorny note_hdr.n_type == note_type) 47531.130Smgorny ret = note_hdr.n_descsz; 47541.130Smgorny } 47551.130Smgorny 47561.130Smgorny offset += note_hdr.n_namesz; 47571.130Smgorny /* fix to alignment */ 47581.146Smgorny offset = roundup(offset, core_hdr.p_align); 47591.130Smgorny 47601.130Smgorny /* if name & type matched above */ 47611.130Smgorny if (ret != -1) { 47621.130Smgorny ssize_t read_len = MIN(buf_len, 47631.130Smgorny note_hdr.n_descsz); 47641.130Smgorny SYSCALL_REQUIRE(pread(core_fd, buf, 47651.130Smgorny read_len, offset) == read_len); 47661.130Smgorny break; 47671.130Smgorny } 47681.130Smgorny 47691.130Smgorny offset += note_hdr.n_descsz; 47701.146Smgorny /* fix to alignment */ 47711.146Smgorny offset = roundup(offset, core_hdr.p_align); 47721.130Smgorny } 47731.130Smgorny } 47741.130Smgorny 47751.130Smgorny elf_end(core_elf); 47761.130Smgorny close(core_fd); 47771.130Smgorny 47781.130Smgorny return ret; 47791.130Smgorny} 47801.130Smgorny 47811.130SmgornyATF_TC(core_dump_procinfo); 47821.130SmgornyATF_TC_HEAD(core_dump_procinfo, tc) 47831.130Smgorny{ 47841.130Smgorny atf_tc_set_md_var(tc, "descr", 47851.130Smgorny "Trigger a core dump and verify its contents."); 47861.130Smgorny} 47871.130Smgorny 47881.130SmgornyATF_TC_BODY(core_dump_procinfo, tc) 47891.130Smgorny{ 47901.130Smgorny const int exitval = 5; 47911.130Smgorny pid_t child, wpid; 47921.130Smgorny#if defined(TWAIT_HAVE_STATUS) 47931.130Smgorny const int sigval = SIGTRAP; 47941.130Smgorny int status; 47951.130Smgorny#endif 47961.130Smgorny char core_path[] = "/tmp/core.XXXXXX"; 47971.130Smgorny int core_fd; 47981.130Smgorny struct netbsd_elfcore_procinfo procinfo; 47991.130Smgorny 48001.130Smgorny DPRINTF("Before forking process PID=%d\n", getpid()); 48011.130Smgorny SYSCALL_REQUIRE((child = fork()) != -1); 48021.130Smgorny if (child == 0) { 48031.130Smgorny DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 48041.130Smgorny FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 48051.130Smgorny 48061.130Smgorny DPRINTF("Before triggering SIGTRAP\n"); 48071.130Smgorny trigger_trap(); 48081.130Smgorny 48091.130Smgorny DPRINTF("Before exiting of the child process\n"); 48101.130Smgorny _exit(exitval); 48111.130Smgorny } 48121.130Smgorny DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 48131.130Smgorny 48141.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48151.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48161.130Smgorny 48171.130Smgorny validate_status_stopped(status, sigval); 48181.130Smgorny 48191.130Smgorny SYSCALL_REQUIRE((core_fd = mkstemp(core_path)) != -1); 48201.130Smgorny close(core_fd); 48211.130Smgorny 48221.130Smgorny DPRINTF("Call DUMPCORE for the child process\n"); 48231.130Smgorny SYSCALL_REQUIRE(ptrace(PT_DUMPCORE, child, core_path, strlen(core_path)) 48241.130Smgorny != -1); 48251.130Smgorny 48261.130Smgorny DPRINTF("Read core file\n"); 48271.130Smgorny ATF_REQUIRE_EQ(core_find_note(core_path, "NetBSD-CORE", 48281.130Smgorny ELF_NOTE_NETBSD_CORE_PROCINFO, &procinfo, sizeof(procinfo)), 48291.130Smgorny sizeof(procinfo)); 48301.130Smgorny 48311.130Smgorny ATF_CHECK_EQ(procinfo.cpi_version, 1); 48321.130Smgorny ATF_CHECK_EQ(procinfo.cpi_cpisize, sizeof(procinfo)); 48331.130Smgorny ATF_CHECK_EQ(procinfo.cpi_signo, SIGTRAP); 48341.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pid, child); 48351.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ppid, getpid()); 48361.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pgrp, getpgid(child)); 48371.130Smgorny ATF_CHECK_EQ(procinfo.cpi_sid, getsid(child)); 48381.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ruid, getuid()); 48391.130Smgorny ATF_CHECK_EQ(procinfo.cpi_euid, geteuid()); 48401.130Smgorny ATF_CHECK_EQ(procinfo.cpi_rgid, getgid()); 48411.130Smgorny ATF_CHECK_EQ(procinfo.cpi_egid, getegid()); 48421.130Smgorny ATF_CHECK_EQ(procinfo.cpi_nlwps, 1); 48431.173Skamil ATF_CHECK(procinfo.cpi_siglwp > 0); 48441.130Smgorny 48451.130Smgorny unlink(core_path); 48461.130Smgorny 48471.130Smgorny DPRINTF("Before resuming the child process where it left off and " 48481.130Smgorny "without signal to be sent\n"); 48491.130Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 48501.130Smgorny 48511.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48521.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 48531.130Smgorny 48541.130Smgorny validate_status_exited(status, exitval); 48551.130Smgorny 48561.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 48571.130Smgorny TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 48581.130Smgorny} 48591.130Smgorny 48601.130Smgorny/// ---------------------------------------------------------------------------- 48611.130Smgorny 48621.138Smgorny#if defined(TWAIT_HAVE_STATUS) 48631.138Smgorny 48641.160Smgorny#define THREAD_CONCURRENT_BREAKPOINT_NUM 50 48651.156Smgorny#define THREAD_CONCURRENT_SIGNALS_NUM 50 48661.161Smgorny#define THREAD_CONCURRENT_WATCHPOINT_NUM 50 48671.138Smgorny 48681.138Smgorny/* List of signals to use for the test */ 48691.138Smgornyconst int thread_concurrent_signals_list[] = { 48701.138Smgorny SIGIO, 48711.138Smgorny SIGXCPU, 48721.138Smgorny SIGXFSZ, 48731.138Smgorny SIGVTALRM, 48741.138Smgorny SIGPROF, 48751.138Smgorny SIGWINCH, 48761.138Smgorny SIGINFO, 48771.138Smgorny SIGUSR1, 48781.138Smgorny SIGUSR2 48791.138Smgorny}; 48801.138Smgorny 48811.157Smgornyenum thread_concurrent_signal_handling { 48821.157Smgorny /* the signal is discarded by debugger */ 48831.157Smgorny TCSH_DISCARD, 48841.157Smgorny /* the handler is set to SIG_IGN */ 48851.157Smgorny TCSH_SIG_IGN, 48861.157Smgorny /* an actual handler is used */ 48871.157Smgorny TCSH_HANDLER 48881.157Smgorny}; 48891.157Smgorny 48901.156Smgornystatic pthread_barrier_t thread_concurrent_barrier; 48911.158Smgornystatic pthread_key_t thread_concurrent_key; 48921.161Smgornystatic uint32_t thread_concurrent_watchpoint_var = 0; 48931.138Smgorny 48941.160Smgornystatic void * 48951.160Smgornythread_concurrent_breakpoint_thread(void *arg) 48961.160Smgorny{ 48971.160Smgorny static volatile int watchme = 1; 48981.160Smgorny pthread_barrier_wait(&thread_concurrent_barrier); 48991.160Smgorny DPRINTF("Before entering breakpoint func from LWP %d\n", _lwp_self()); 49001.160Smgorny check_happy(watchme); 49011.160Smgorny return NULL; 49021.160Smgorny} 49031.160Smgorny 49041.157Smgornystatic void 49051.157Smgornythread_concurrent_sig_handler(int sig) 49061.157Smgorny{ 49071.158Smgorny void *tls_val = pthread_getspecific(thread_concurrent_key); 49081.158Smgorny DPRINTF("Before increment, LWP %d tls_val=%p\n", _lwp_self(), tls_val); 49091.158Smgorny FORKEE_ASSERT(pthread_setspecific(thread_concurrent_key, 49101.158Smgorny (void*)((uintptr_t)tls_val + 1)) == 0); 49111.157Smgorny} 49121.157Smgorny 49131.138Smgornystatic void * 49141.138Smgornythread_concurrent_signals_thread(void *arg) 49151.138Smgorny{ 49161.138Smgorny int sigval = thread_concurrent_signals_list[ 49171.138Smgorny _lwp_self() % __arraycount(thread_concurrent_signals_list)]; 49181.158Smgorny enum thread_concurrent_signal_handling *signal_handle = arg; 49191.158Smgorny void *tls_val; 49201.158Smgorny 49211.156Smgorny pthread_barrier_wait(&thread_concurrent_barrier); 49221.138Smgorny DPRINTF("Before raising %s from LWP %d\n", strsignal(sigval), 49231.138Smgorny _lwp_self()); 49241.138Smgorny pthread_kill(pthread_self(), sigval); 49251.158Smgorny if (*signal_handle == TCSH_HANDLER) { 49261.158Smgorny tls_val = pthread_getspecific(thread_concurrent_key); 49271.158Smgorny DPRINTF("After raising, LWP %d tls_val=%p\n", _lwp_self(), tls_val); 49281.158Smgorny FORKEE_ASSERT(tls_val == (void*)1); 49291.158Smgorny } 49301.138Smgorny return NULL; 49311.138Smgorny} 49321.138Smgorny 49331.161Smgornystatic void * 49341.161Smgornythread_concurrent_watchpoint_thread(void *arg) 49351.161Smgorny{ 49361.161Smgorny pthread_barrier_wait(&thread_concurrent_barrier); 49371.161Smgorny DPRINTF("Before modifying var from LWP %d\n", _lwp_self()); 49381.161Smgorny thread_concurrent_watchpoint_var = 1; 49391.161Smgorny return NULL; 49401.161Smgorny} 49411.161Smgorny 49421.160Smgorny#if defined(__i386__) || defined(__x86_64__) 49431.160Smgornyenum thread_concurrent_sigtrap_event { 49441.160Smgorny TCSE_UNKNOWN, 49451.161Smgorny TCSE_BREAKPOINT, 49461.161Smgorny TCSE_WATCHPOINT 49471.160Smgorny}; 49481.160Smgorny 49491.160Smgornystatic void 49501.160Smgornythread_concurrent_lwp_setup(pid_t child, lwpid_t lwpid); 49511.160Smgornystatic enum thread_concurrent_sigtrap_event 49521.160Smgornythread_concurrent_handle_sigtrap(pid_t child, ptrace_siginfo_t *info); 49531.160Smgorny#endif 49541.160Smgorny 49551.156Smgornystatic void 49561.157Smgornythread_concurrent_test(enum thread_concurrent_signal_handling signal_handle, 49571.161Smgorny int breakpoint_threads, int signal_threads, int watchpoint_threads) 49581.138Smgorny{ 49591.138Smgorny const int exitval = 5; 49601.138Smgorny const int sigval = SIGSTOP; 49611.138Smgorny pid_t child, wpid; 49621.138Smgorny int status; 49631.141Skamil struct lwp_event_count signal_counts[THREAD_CONCURRENT_SIGNALS_NUM] 49641.141Skamil = {{0, 0}}; 49651.160Smgorny struct lwp_event_count bp_counts[THREAD_CONCURRENT_BREAKPOINT_NUM] 49661.160Smgorny = {{0, 0}}; 49671.161Smgorny struct lwp_event_count wp_counts[THREAD_CONCURRENT_BREAKPOINT_NUM] 49681.161Smgorny = {{0, 0}}; 49691.159Smgorny ptrace_event_t event; 49701.156Smgorny int i; 49711.156Smgorny 49721.164Skamil#if defined(HAVE_DBREGS) 49731.164Skamil if (!can_we_set_dbregs()) { 49741.164Skamil atf_tc_skip("Either run this test as root or set sysctl(3) " 49751.164Skamil "security.models.extensions.user_set_dbregs to 1"); 49761.164Skamil } 49771.164Skamil#endif 49781.164Skamil 49791.164Skamil atf_tc_skip("PR kern/54960"); 49801.157Smgorny 49811.156Smgorny /* Protect against out-of-bounds array access. */ 49821.160Smgorny ATF_REQUIRE(breakpoint_threads <= THREAD_CONCURRENT_BREAKPOINT_NUM); 49831.156Smgorny ATF_REQUIRE(signal_threads <= THREAD_CONCURRENT_SIGNALS_NUM); 49841.161Smgorny ATF_REQUIRE(watchpoint_threads <= THREAD_CONCURRENT_WATCHPOINT_NUM); 49851.138Smgorny 49861.138Smgorny DPRINTF("Before forking process PID=%d\n", getpid()); 49871.138Smgorny SYSCALL_REQUIRE((child = fork()) != -1); 49881.138Smgorny if (child == 0) { 49891.160Smgorny pthread_t bp_threads[THREAD_CONCURRENT_BREAKPOINT_NUM]; 49901.156Smgorny pthread_t sig_threads[THREAD_CONCURRENT_SIGNALS_NUM]; 49911.161Smgorny pthread_t wp_threads[THREAD_CONCURRENT_WATCHPOINT_NUM]; 49921.138Smgorny 49931.138Smgorny DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 49941.138Smgorny FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 49951.138Smgorny 49961.138Smgorny DPRINTF("Before raising %s from child\n", strsignal(sigval)); 49971.138Smgorny FORKEE_ASSERT(raise(sigval) == 0); 49981.138Smgorny 49991.157Smgorny if (signal_handle != TCSH_DISCARD) { 50001.157Smgorny struct sigaction sa; 50011.157Smgorny unsigned int j; 50021.157Smgorny 50031.157Smgorny memset(&sa, 0, sizeof(sa)); 50041.157Smgorny if (signal_handle == TCSH_SIG_IGN) 50051.157Smgorny sa.sa_handler = SIG_IGN; 50061.157Smgorny else 50071.157Smgorny sa.sa_handler = thread_concurrent_sig_handler; 50081.157Smgorny sigemptyset(&sa.sa_mask); 50091.157Smgorny 50101.157Smgorny for (j = 0; 50111.157Smgorny j < __arraycount(thread_concurrent_signals_list); 50121.157Smgorny j++) 50131.157Smgorny FORKEE_ASSERT(sigaction( 50141.157Smgorny thread_concurrent_signals_list[j], &sa, NULL) 50151.157Smgorny != -1); 50161.157Smgorny } 50171.157Smgorny 50181.138Smgorny DPRINTF("Before starting threads from the child\n"); 50191.138Smgorny FORKEE_ASSERT(pthread_barrier_init( 50201.156Smgorny &thread_concurrent_barrier, NULL, 50211.161Smgorny breakpoint_threads + signal_threads + watchpoint_threads) 50221.161Smgorny == 0); 50231.158Smgorny FORKEE_ASSERT(pthread_key_create(&thread_concurrent_key, NULL) 50241.158Smgorny == 0); 50251.138Smgorny 50261.156Smgorny for (i = 0; i < signal_threads; i++) { 50271.156Smgorny FORKEE_ASSERT(pthread_create(&sig_threads[i], NULL, 50281.158Smgorny thread_concurrent_signals_thread, 50291.158Smgorny &signal_handle) == 0); 50301.138Smgorny } 50311.160Smgorny for (i = 0; i < breakpoint_threads; i++) { 50321.160Smgorny FORKEE_ASSERT(pthread_create(&bp_threads[i], NULL, 50331.160Smgorny thread_concurrent_breakpoint_thread, NULL) == 0); 50341.160Smgorny } 50351.161Smgorny for (i = 0; i < watchpoint_threads; i++) { 50361.161Smgorny FORKEE_ASSERT(pthread_create(&wp_threads[i], NULL, 50371.161Smgorny thread_concurrent_watchpoint_thread, NULL) == 0); 50381.161Smgorny } 50391.138Smgorny 50401.138Smgorny DPRINTF("Before joining threads from the child\n"); 50411.161Smgorny for (i = 0; i < watchpoint_threads; i++) { 50421.161Smgorny FORKEE_ASSERT(pthread_join(wp_threads[i], NULL) == 0); 50431.161Smgorny } 50441.160Smgorny for (i = 0; i < breakpoint_threads; i++) { 50451.160Smgorny FORKEE_ASSERT(pthread_join(bp_threads[i], NULL) == 0); 50461.160Smgorny } 50471.156Smgorny for (i = 0; i < signal_threads; i++) { 50481.156Smgorny FORKEE_ASSERT(pthread_join(sig_threads[i], NULL) == 0); 50491.138Smgorny } 50501.138Smgorny 50511.158Smgorny FORKEE_ASSERT(pthread_key_delete(thread_concurrent_key) == 0); 50521.138Smgorny FORKEE_ASSERT(pthread_barrier_destroy( 50531.156Smgorny &thread_concurrent_barrier) == 0); 50541.138Smgorny 50551.138Smgorny DPRINTF("Before exiting of the child process\n"); 50561.138Smgorny _exit(exitval); 50571.138Smgorny } 50581.138Smgorny DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 50591.138Smgorny 50601.138Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 50611.138Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 50621.138Smgorny 50631.138Smgorny validate_status_stopped(status, sigval); 50641.138Smgorny 50651.159Smgorny DPRINTF("Set LWP event mask for the child process\n"); 50661.159Smgorny memset(&event, 0, sizeof(event)); 50671.159Smgorny event.pe_set_event |= PTRACE_LWP_CREATE; 50681.159Smgorny SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, sizeof(event)) 50691.159Smgorny != -1); 50701.159Smgorny 50711.138Smgorny DPRINTF("Before resuming the child process where it left off\n"); 50721.138Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 50731.138Smgorny 50741.138Smgorny DPRINTF("Before entering signal collection loop\n"); 50751.138Smgorny while (1) { 50761.138Smgorny ptrace_siginfo_t info; 50771.138Smgorny 50781.138Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 50791.138Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 50801.138Smgorny child); 50811.138Smgorny if (WIFEXITED(status)) 50821.138Smgorny break; 50831.138Smgorny /* Note: we use validate_status_stopped() to get nice error 50841.138Smgorny * message. Signal is irrelevant since it won't be reached. 50851.138Smgorny */ 50861.138Smgorny else if (!WIFSTOPPED(status)) 50871.138Smgorny validate_status_stopped(status, 0); 50881.138Smgorny 50891.138Smgorny DPRINTF("Before calling PT_GET_SIGINFO\n"); 50901.138Smgorny SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 50911.138Smgorny sizeof(info)) != -1); 50921.138Smgorny 50931.138Smgorny DPRINTF("Received signal %d from LWP %d (wait: %d)\n", 50941.138Smgorny info.psi_siginfo.si_signo, info.psi_lwpid, 50951.138Smgorny WSTOPSIG(status)); 50961.138Smgorny 50971.159Smgorny ATF_CHECK_EQ_MSG(info.psi_siginfo.si_signo, WSTOPSIG(status), 50981.159Smgorny "lwp=%d, WSTOPSIG=%d, psi_siginfo=%d", info.psi_lwpid, 50991.159Smgorny WSTOPSIG(status), info.psi_siginfo.si_signo); 51001.159Smgorny 51011.159Smgorny if (WSTOPSIG(status) != SIGTRAP) { 51021.159Smgorny int expected_sig = 51031.159Smgorny thread_concurrent_signals_list[info.psi_lwpid % 51041.159Smgorny __arraycount(thread_concurrent_signals_list)]; 51051.159Smgorny ATF_CHECK_EQ_MSG(WSTOPSIG(status), expected_sig, 51061.159Smgorny "lwp=%d, expected %d, got %d", info.psi_lwpid, 51071.159Smgorny expected_sig, WSTOPSIG(status)); 51081.138Smgorny 51091.159Smgorny *FIND_EVENT_COUNT(signal_counts, info.psi_lwpid) += 1; 51101.160Smgorny } else if (info.psi_siginfo.si_code == TRAP_LWP) { 51111.160Smgorny#if defined(__i386__) || defined(__x86_64__) 51121.160Smgorny thread_concurrent_lwp_setup(child, info.psi_lwpid); 51131.160Smgorny#endif 51141.159Smgorny } else { 51151.160Smgorny#if defined(__i386__) || defined(__x86_64__) 51161.160Smgorny switch (thread_concurrent_handle_sigtrap(child, &info)) { 51171.160Smgorny case TCSE_UNKNOWN: 51181.160Smgorny /* already reported inside the function */ 51191.160Smgorny break; 51201.160Smgorny case TCSE_BREAKPOINT: 51211.160Smgorny *FIND_EVENT_COUNT(bp_counts, 51221.160Smgorny info.psi_lwpid) += 1; 51231.160Smgorny break; 51241.161Smgorny case TCSE_WATCHPOINT: 51251.161Smgorny *FIND_EVENT_COUNT(wp_counts, 51261.161Smgorny info.psi_lwpid) += 1; 51271.161Smgorny break; 51281.160Smgorny } 51291.160Smgorny#else 51301.160Smgorny ATF_CHECK_MSG(0, "Unexpected SIGTRAP, si_code=%d\n", 51311.160Smgorny info.psi_siginfo.si_code); 51321.160Smgorny#endif 51331.159Smgorny } 51341.138Smgorny 51351.138Smgorny DPRINTF("Before resuming the child process\n"); 51361.157Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 51371.159Smgorny signal_handle != TCSH_DISCARD && WSTOPSIG(status) != SIGTRAP 51381.159Smgorny ? WSTOPSIG(status) : 0) != -1); 51391.138Smgorny } 51401.138Smgorny 51411.156Smgorny for (i = 0; i < signal_threads; i++) 51421.141Skamil ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 1, 51431.141Skamil "signal_counts[%d].lec_count=%d; lec_lwp=%d", 51441.141Skamil i, signal_counts[i].lec_count, signal_counts[i].lec_lwp); 51451.156Smgorny for (i = signal_threads; i < THREAD_CONCURRENT_SIGNALS_NUM; i++) 51461.156Smgorny ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 0, 51471.156Smgorny "extraneous signal_counts[%d].lec_count=%d; lec_lwp=%d", 51481.156Smgorny i, signal_counts[i].lec_count, signal_counts[i].lec_lwp); 51491.138Smgorny 51501.160Smgorny for (i = 0; i < breakpoint_threads; i++) 51511.160Smgorny ATF_CHECK_EQ_MSG(bp_counts[i].lec_count, 1, 51521.160Smgorny "bp_counts[%d].lec_count=%d; lec_lwp=%d", 51531.160Smgorny i, bp_counts[i].lec_count, bp_counts[i].lec_lwp); 51541.160Smgorny for (i = breakpoint_threads; i < THREAD_CONCURRENT_BREAKPOINT_NUM; i++) 51551.160Smgorny ATF_CHECK_EQ_MSG(bp_counts[i].lec_count, 0, 51561.160Smgorny "extraneous bp_counts[%d].lec_count=%d; lec_lwp=%d", 51571.160Smgorny i, bp_counts[i].lec_count, bp_counts[i].lec_lwp); 51581.160Smgorny 51591.161Smgorny for (i = 0; i < watchpoint_threads; i++) 51601.161Smgorny ATF_CHECK_EQ_MSG(wp_counts[i].lec_count, 1, 51611.161Smgorny "wp_counts[%d].lec_count=%d; lec_lwp=%d", 51621.161Smgorny i, wp_counts[i].lec_count, wp_counts[i].lec_lwp); 51631.161Smgorny for (i = watchpoint_threads; i < THREAD_CONCURRENT_WATCHPOINT_NUM; i++) 51641.161Smgorny ATF_CHECK_EQ_MSG(wp_counts[i].lec_count, 0, 51651.161Smgorny "extraneous wp_counts[%d].lec_count=%d; lec_lwp=%d", 51661.161Smgorny i, wp_counts[i].lec_count, wp_counts[i].lec_lwp); 51671.161Smgorny 51681.138Smgorny validate_status_exited(status, exitval); 51691.138Smgorny} 51701.138Smgorny 51711.161Smgorny#define THREAD_CONCURRENT_TEST(test, sig_hdl, bps, sigs, wps, descr) \ 51721.156SmgornyATF_TC(test); \ 51731.156SmgornyATF_TC_HEAD(test, tc) \ 51741.156Smgorny{ \ 51751.156Smgorny atf_tc_set_md_var(tc, "descr", descr); \ 51761.156Smgorny} \ 51771.156Smgorny \ 51781.156SmgornyATF_TC_BODY(test, tc) \ 51791.156Smgorny{ \ 51801.161Smgorny thread_concurrent_test(sig_hdl, bps, sigs, wps); \ 51811.156Smgorny} 51821.156Smgorny 51831.157SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_signals, TCSH_DISCARD, 51841.161Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, 0, 51851.157Smgorny "Verify that concurrent signals issued to a single thread are reported " 51861.157Smgorny "correctly"); 51871.157SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_signals_sig_ign, TCSH_SIG_IGN, 51881.161Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, 0, 51891.157Smgorny "Verify that concurrent signals issued to a single thread are reported " 51901.157Smgorny "correctly and passed back to SIG_IGN handler"); 51911.157SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_signals_handler, TCSH_HANDLER, 51921.161Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, 0, 51931.157Smgorny "Verify that concurrent signals issued to a single thread are reported " 51941.157Smgorny "correctly and passed back to a handler function"); 51951.156Smgorny 51961.163Skamil#if defined(__i386__) || defined(__x86_64__) 51971.160SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_breakpoints, TCSH_DISCARD, 51981.161Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, 0, 0, 51991.161Smgorny "Verify that concurrent breakpoints are reported correctly"); 52001.161SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_watchpoints, TCSH_DISCARD, 52011.161Smgorny 0, 0, THREAD_CONCURRENT_WATCHPOINT_NUM, 52021.160Smgorny "Verify that concurrent breakpoints are reported correctly"); 52031.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp, TCSH_DISCARD, 52041.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, 0, THREAD_CONCURRENT_WATCHPOINT_NUM, 52051.162Smgorny "Verify that concurrent breakpoints and watchpoints are reported " 52061.162Smgorny "correctly"); 52071.162Smgorny 52081.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_sig, TCSH_DISCARD, 52091.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0, 52101.162Smgorny "Verify that concurrent breakpoints and signals are reported correctly"); 52111.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_sig_sig_ign, TCSH_SIG_IGN, 52121.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0, 52131.162Smgorny "Verify that concurrent breakpoints and signals are reported correctly " 52141.162Smgorny "and passed back to SIG_IGN handler"); 52151.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_sig_handler, TCSH_HANDLER, 52161.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0, 52171.162Smgorny "Verify that concurrent breakpoints and signals are reported correctly " 52181.162Smgorny "and passed back to a handler function"); 52191.162Smgorny 52201.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_wp_sig, TCSH_DISCARD, 52211.162Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM, 52221.162Smgorny "Verify that concurrent watchpoints and signals are reported correctly"); 52231.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_wp_sig_sig_ign, TCSH_SIG_IGN, 52241.162Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM, 52251.162Smgorny "Verify that concurrent watchpoints and signals are reported correctly " 52261.162Smgorny "and passed back to SIG_IGN handler"); 52271.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_wp_sig_handler, TCSH_HANDLER, 52281.162Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM, 52291.162Smgorny "Verify that concurrent watchpoints and signals are reported correctly " 52301.162Smgorny "and passed back to a handler function"); 52311.162Smgorny 52321.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig, TCSH_DISCARD, 52331.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 52341.162Smgorny THREAD_CONCURRENT_WATCHPOINT_NUM, 52351.162Smgorny "Verify that concurrent breakpoints, watchpoints and signals are reported " 52361.162Smgorny "correctly"); 52371.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig_sig_ign, TCSH_SIG_IGN, 52381.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 52391.162Smgorny THREAD_CONCURRENT_WATCHPOINT_NUM, 52401.162Smgorny "Verify that concurrent breakpoints, watchpoints and signals are reported " 52411.162Smgorny "correctly and passed back to SIG_IGN handler"); 52421.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig_handler, TCSH_HANDLER, 52431.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 52441.162Smgorny THREAD_CONCURRENT_WATCHPOINT_NUM, 52451.162Smgorny "Verify that concurrent breakpoints, watchpoints and signals are reported " 52461.162Smgorny "correctly and passed back to a handler function"); 52471.163Skamil#endif 52481.160Smgorny 52491.138Smgorny#endif /*defined(TWAIT_HAVE_STATUS)*/ 52501.138Smgorny 52511.138Smgorny/// ---------------------------------------------------------------------------- 52521.138Smgorny 52531.174Skamil#include "t_ptrace_register_wait.h" 52541.175Skamil#include "t_ptrace_syscall_wait.h" 52551.176Skamil#include "t_ptrace_step_wait.h" 52561.177Skamil#include "t_ptrace_kill_wait.h" 52571.178Skamil#include "t_ptrace_bytetransfer_wait.h" 52581.179Skamil#include "t_ptrace_clone_wait.h" 52591.180Skamil#include "t_ptrace_fork_wait.h" 52601.174Skamil 52611.174Skamil/// ---------------------------------------------------------------------------- 52621.174Skamil 52631.1Skamil#include "t_ptrace_amd64_wait.h" 52641.1Skamil#include "t_ptrace_i386_wait.h" 52651.1Skamil#include "t_ptrace_x86_wait.h" 52661.1Skamil 52671.165Skamil/// ---------------------------------------------------------------------------- 52681.165Skamil 52691.165Skamil#else 52701.165SkamilATF_TC(dummy); 52711.165SkamilATF_TC_HEAD(dummy, tc) 52721.165Skamil{ 52731.165Skamil atf_tc_set_md_var(tc, "descr", "A dummy test"); 52741.165Skamil} 52751.165Skamil 52761.165SkamilATF_TC_BODY(dummy, tc) 52771.165Skamil{ 52781.165Skamil 52791.165Skamil // Dummy, skipped 52801.165Skamil // The ATF framework requires at least a single defined test. 52811.165Skamil} 52821.165Skamil#endif 52831.165Skamil 52841.1SkamilATF_TP_ADD_TCS(tp) 52851.1Skamil{ 52861.1Skamil setvbuf(stdout, NULL, _IONBF, 0); 52871.1Skamil setvbuf(stderr, NULL, _IONBF, 0); 52881.33Skamil 52891.165Skamil#ifdef ENABLE_TESTS 52901.36Skamil ATF_TP_ADD_TC(tp, traceme_raise1); 52911.33Skamil ATF_TP_ADD_TC(tp, traceme_raise2); 52921.33Skamil ATF_TP_ADD_TC(tp, traceme_raise3); 52931.33Skamil ATF_TP_ADD_TC(tp, traceme_raise4); 52941.33Skamil ATF_TP_ADD_TC(tp, traceme_raise5); 52951.85Skamil ATF_TP_ADD_TC(tp, traceme_raise6); 52961.85Skamil ATF_TP_ADD_TC(tp, traceme_raise7); 52971.85Skamil ATF_TP_ADD_TC(tp, traceme_raise8); 52981.85Skamil ATF_TP_ADD_TC(tp, traceme_raise9); 52991.85Skamil ATF_TP_ADD_TC(tp, traceme_raise10); 53001.33Skamil 53011.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored1); 53021.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored2); 53031.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored3); 53041.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored4); 53051.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored5); 53061.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored6); 53071.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored7); 53081.87Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_ignored8); 53091.87Skamil 53101.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked1); 53111.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked2); 53121.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked3); 53131.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked4); 53141.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked5); 53151.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked6); 53161.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked7); 53171.86Skamil ATF_TP_ADD_TC(tp, traceme_raisesignal_masked8); 53181.86Skamil 53191.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_trap); 53201.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_segv); 53211.71Skamil ATF_TP_ADD_TC(tp, traceme_crash_ill); 53221.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_fpe); 53231.59Skamil ATF_TP_ADD_TC(tp, traceme_crash_bus); 53241.59Skamil 53251.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_trap); 53261.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_segv); 53271.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_ill); 53281.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_fpe); 53291.88Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_crash_bus); 53301.88Skamil 53311.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_trap); 53321.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_segv); 53331.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_ill); 53341.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_fpe); 53351.88Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_crash_bus); 53361.88Skamil 53371.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle1); 53381.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle2); 53391.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle3); 53401.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle4); 53411.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle5); 53421.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle6); 53431.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle7); 53441.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_handle8); 53451.50Skamil 53461.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked1); 53471.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked2); 53481.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked3); 53491.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked4); 53501.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked5); 53511.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked6); 53521.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked7); 53531.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_masked8); 53541.50Skamil 53551.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored1); 53561.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored2); 53571.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored3); 53581.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored4); 53591.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored5); 53601.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored6); 53611.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored7); 53621.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_ignored8); 53631.50Skamil 53641.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple1); 53651.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple2); 53661.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple3); 53671.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple4); 53681.50Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple5); 53691.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple6); 53701.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple7); 53711.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple8); 53721.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple9); 53731.85Skamil ATF_TP_ADD_TC(tp, traceme_sendsignal_simple10); 53741.1Skamil 53751.37Skamil ATF_TP_ADD_TC(tp, traceme_pid1_parent); 53761.37Skamil 53771.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise1); 53781.46Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise2); 53791.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise3); 53801.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise4); 53811.40Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise5); 53821.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise6); 53831.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise7); 53841.47Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise8); 53851.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise9); 53861.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise10); 53871.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise11); 53881.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise12); 53891.85Skamil ATF_TP_ADD_TC(tp, traceme_vfork_raise13); 53901.40Skamil 53911.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_trap); 53921.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_segv); 53931.71Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_ill); 53941.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_fpe); 53951.52Skamil ATF_TP_ADD_TC(tp, traceme_vfork_crash_bus); 53961.41Skamil 53971.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_trap); 53981.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_segv); 53991.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_ill); 54001.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_fpe); 54011.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_crash_bus); 54021.92Skamil 54031.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_trap); 54041.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_segv); 54051.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_ill); 54061.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_fpe); 54071.92Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_crash_bus); 54081.92Skamil 54091.43Skamil ATF_TP_ADD_TC(tp, traceme_vfork_exec); 54101.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec); 54111.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec); 54121.43Skamil 54131.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_trap); 54141.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_segv); 54151.71Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_ill); 54161.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_fpe); 54171.59Skamil ATF_TP_ADD_TC_HAVE_PID(tp, unrelated_tracer_sees_crash_bus); 54181.59Skamil 54191.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 54201.94Skamil unrelated_tracer_sees_signalmasked_crash_trap); 54211.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 54221.94Skamil unrelated_tracer_sees_signalmasked_crash_segv); 54231.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 54241.94Skamil unrelated_tracer_sees_signalmasked_crash_ill); 54251.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 54261.94Skamil unrelated_tracer_sees_signalmasked_crash_fpe); 54271.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 54281.94Skamil unrelated_tracer_sees_signalmasked_crash_bus); 54291.94Skamil 54301.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 54311.94Skamil unrelated_tracer_sees_signalignored_crash_trap); 54321.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 54331.94Skamil unrelated_tracer_sees_signalignored_crash_segv); 54341.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 54351.94Skamil unrelated_tracer_sees_signalignored_crash_ill); 54361.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 54371.94Skamil unrelated_tracer_sees_signalignored_crash_fpe); 54381.94Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 54391.94Skamil unrelated_tracer_sees_signalignored_crash_bus); 54401.94Skamil 54411.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent); 54421.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates); 54431.61Skre ATF_TP_ADD_TC_HAVE_PID(tp, 54441.61Skre unrelated_tracer_sees_terminaton_before_the_parent); 54451.67Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process); 54461.51Skamil 54471.51Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_child); 54481.66Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child); 54491.51Skamil 54501.51Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_parent); 54511.65Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent); 54521.51Skamil 54531.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 54541.51Skamil tracee_sees_its_original_parent_getppid); 54551.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 54561.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2); 54571.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 54581.51Skamil tracee_sees_its_original_parent_procfs_status); 54591.1Skamil 54601.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_empty); 54611.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_fork); 54621.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork); 54631.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done); 54641.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create); 54651.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit); 54661.125Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_posix_spawn); 54671.1Skamil 54681.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8); 54691.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16); 54701.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32); 54711.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64); 54721.54Skamil 54731.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8); 54741.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16); 54751.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32); 54761.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64); 54771.54Skamil 54781.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8); 54791.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16); 54801.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32); 54811.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64); 54821.54Skamil 54831.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8); 54841.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16); 54851.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32); 54861.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64); 54871.54Skamil 54881.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d); 54891.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i); 54901.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d); 54911.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i); 54921.54Skamil 54931.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text); 54941.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text); 54951.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text); 54961.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text); 54971.54Skamil 54981.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text); 54991.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text); 55001.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text); 55011.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text); 55021.54Skamil 55031.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text); 55041.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text); 55051.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text); 55061.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text); 55071.54Skamil 55081.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text); 55091.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text); 55101.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text); 55111.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text); 55121.54Skamil 55131.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text); 55141.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text); 55151.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text); 55161.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text); 55171.1Skamil 55181.54Skamil ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv); 55191.1Skamil 55201.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i); 55211.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d); 55221.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i); 55231.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d); 55241.101Skamil 55251.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i); 55261.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d); 55271.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i); 55281.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d); 55291.101Skamil 55301.101Skamil ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv); 55311.101Skamil 55321.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i); 55331.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d); 55341.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i); 55351.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d); 55361.115Skamil 55371.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i); 55381.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d); 55391.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i); 55401.115Skamil ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d); 55411.115Skamil 55421.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0); 55431.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1); 55441.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2); 55451.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3); 55461.77Skamil 55471.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus); 55481.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus); 55491.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus); 55501.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus); 55511.143Skamil 55521.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus_pl_sigmask); 55531.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus_pl_sigmask); 55541.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus_pl_sigmask); 55551.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus_pl_sigmask); 55561.143Skamil 55571.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus_pl_name); 55581.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus_pl_name); 55591.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus_pl_name); 55601.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus_pl_name); 55611.143Skamil 55621.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus_pl_private); 55631.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus_pl_private); 55641.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus_pl_private); 55651.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus_pl_private); 55661.143Skamil 55671.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0); 55681.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1); 55691.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2); 55701.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3); 55711.143Skamil 55721.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0_pl_sigmask); 55731.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1_pl_sigmask); 55741.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2_pl_sigmask); 55751.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3_pl_sigmask); 55761.143Skamil 55771.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0_pl_name); 55781.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1_pl_name); 55791.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2_pl_name); 55801.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3_pl_name); 55811.143Skamil 55821.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0_pl_private); 55831.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1_pl_private); 55841.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2_pl_private); 55851.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3_pl_private); 55861.143Skamil 55871.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0); 55881.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1); 55891.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2); 55901.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3); 55911.1Skamil 55921.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_unmodified); 55931.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_faked); 55941.79Skamil 55951.82Skamil ATF_TP_ADD_TC(tp, traceme_exec); 55961.97Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_exec); 55971.97Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_exec); 55981.1Skamil 55991.119Skamil ATF_TP_ADD_TC(tp, trace_thread_nolwpevents); 56001.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpexit); 56011.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate); 56021.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit); 56031.1Skamil 56041.153Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpexit_masked_sigtrap); 56051.153Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_masked_sigtrap); 56061.153Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit_masked_sigtrap); 56071.153Skamil 56081.84Skamil ATF_TP_ADD_TC(tp, signal_mask_unrelated); 56091.84Skamil 56101.151Skamil ATF_TP_ADD_TC(tp, threads_and_exec); 56111.151Skamil 56121.154Skamil ATF_TP_ADD_TC(tp, suspend_no_deadlock); 56131.1Skamil 56141.155Skamil ATF_TP_ADD_TC(tp, resume); 56151.1Skamil 56161.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue); 56171.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall); 56181.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach); 56191.122Skamil 56201.130Smgorny ATF_TP_ADD_TC(tp, core_dump_procinfo); 56211.130Smgorny 56221.138Smgorny#if defined(TWAIT_HAVE_STATUS) 56231.138Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_signals); 56241.157Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_signals_sig_ign); 56251.157Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_signals_handler); 56261.160Smgorny#if defined(__i386__) || defined(__x86_64__) 56271.160Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_breakpoints); 56281.161Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_watchpoints); 56291.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp); 56301.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_sig); 56311.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_sig_sig_ign); 56321.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_sig_handler); 56331.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_wp_sig); 56341.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_wp_sig_sig_ign); 56351.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_wp_sig_handler); 56361.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp_sig); 56371.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp_sig_sig_ign); 56381.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp_sig_handler); 56391.160Smgorny#endif 56401.138Smgorny#endif 56411.138Smgorny 56421.174Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_REGISTER(); 56431.175Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_SYSCALL(); 56441.176Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_STEP(); 56451.177Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_KILL(); 56461.178Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_BYTETRANSFER(); 56471.179Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_CLONE(); 56481.180Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_FORK(); 56491.174Skamil 56501.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64(); 56511.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_I386(); 56521.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_X86(); 56531.1Skamil 56541.165Skamil#else 56551.165Skamil ATF_TP_ADD_TC(tp, dummy); 56561.165Skamil#endif 56571.165Skamil 56581.1Skamil return atf_no_error(); 56591.1Skamil} 5660