t_ptrace_wait.c revision 1.183
11.183Skamil/* $NetBSD: t_ptrace_wait.c,v 1.183 2020/05/05 00:01:14 kamil Exp $ */ 21.1Skamil 31.1Skamil/*- 41.181Skamil * Copyright (c) 2016, 2017, 2018, 2019, 2020 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.183Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.183 2020/05/05 00:01:14 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.37SkamilATF_TC(traceme_pid1_parent); 1071.37SkamilATF_TC_HEAD(traceme_pid1_parent, tc) 1081.37Skamil{ 1091.181Skamil atf_tc_set_md_var(tc, "descr", 1101.181Skamil "Verify that PT_TRACE_ME is not allowed when our parent is PID1"); 1111.43Skamil} 1121.43Skamil 1131.181SkamilATF_TC_BODY(traceme_pid1_parent, tc) 1141.59Skamil{ 1151.181Skamil struct msg_fds parent_child; 1161.181Skamil int exitval_child1 = 1, exitval_child2 = 2; 1171.181Skamil pid_t child1, child2, wpid; 1181.59Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 1191.59Skamil#if defined(TWAIT_HAVE_STATUS) 1201.59Skamil int status; 1211.59Skamil#endif 1221.94Skamil 1231.181Skamil SYSCALL_REQUIRE(msg_open(&parent_child) == 0); 1241.61Skre 1251.181Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 1261.181Skamil SYSCALL_REQUIRE((child1 = fork()) != -1); 1271.181Skamil if (child1 == 0) { 1281.181Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 1291.181Skamil SYSCALL_REQUIRE((child2 = fork()) != -1); 1301.181Skamil if (child2 != 0) { 1311.181Skamil DPRINTF("Parent process PID=%d, child2's PID=%d\n", 1321.181Skamil getpid(), child2); 1331.181Skamil _exit(exitval_child1); 1341.94Skamil } 1351.181Skamil CHILD_FROM_PARENT("exit child1", parent_child, msg); 1361.94Skamil 1371.181Skamil DPRINTF("Assert that our parent is PID1 (initproc)\n"); 1381.181Skamil FORKEE_ASSERT_EQ(getppid(), 1); 1391.94Skamil 1401.181Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1411.181Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) == -1); 1421.181Skamil SYSCALL_REQUIRE_ERRNO(errno, EPERM); 1431.94Skamil 1441.181Skamil CHILD_TO_PARENT("child2 exiting", parent_child, msg); 1451.94Skamil 1461.181Skamil _exit(exitval_child2); 1471.181Skamil } 1481.181Skamil DPRINTF("Parent process PID=%d, child1's PID=%d\n", getpid(), child1); 1491.94Skamil 1501.181Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1511.181Skamil TWAIT_REQUIRE_SUCCESS( 1521.181Skamil wpid = TWAIT_GENERIC(child1, &status, WEXITED), child1); 1531.94Skamil 1541.181Skamil validate_status_exited(status, exitval_child1); 1551.94Skamil 1561.181Skamil DPRINTF("Notify that child1 is dead\n"); 1571.181Skamil PARENT_TO_CHILD("exit child1", parent_child, msg); 1581.94Skamil 1591.181Skamil DPRINTF("Wait for exiting of child2\n"); 1601.181Skamil PARENT_FROM_CHILD("child2 exiting", parent_child, msg); 1611.181Skamil} 1621.94Skamil 1631.181Skamil/// ---------------------------------------------------------------------------- 1641.59Skamil 1651.181Skamilstatic void 1661.181Skamiltraceme_vfork_exec(bool masked, bool ignored) 1671.181Skamil{ 1681.181Skamil const int sigval = SIGTRAP; 1691.181Skamil pid_t child, wpid; 1701.181Skamil#if defined(TWAIT_HAVE_STATUS) 1711.181Skamil int status; 1721.181Skamil#endif 1731.181Skamil struct sigaction sa; 1741.181Skamil struct ptrace_siginfo info; 1751.181Skamil sigset_t intmask; 1761.181Skamil struct kinfo_proc2 kp; 1771.181Skamil size_t len = sizeof(kp); 1781.59Skamil 1791.181Skamil int name[6]; 1801.181Skamil const size_t namelen = __arraycount(name); 1811.181Skamil ki_sigset_t kp_sigmask; 1821.181Skamil ki_sigset_t kp_sigignore; 1831.59Skamil 1841.181Skamil memset(&info, 0, sizeof(info)); 1851.94Skamil 1861.181Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 1871.181Skamil SYSCALL_REQUIRE((child = vfork()) != -1); 1881.181Skamil if (child == 0) { 1891.181Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1901.181Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1911.94Skamil 1921.94Skamil if (masked) { 1931.181Skamil sigemptyset(&intmask); 1941.181Skamil sigaddset(&intmask, sigval); 1951.181Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 1961.181Skamil } 1971.94Skamil 1981.181Skamil if (ignored) { 1991.181Skamil memset(&sa, 0, sizeof(sa)); 2001.181Skamil sa.sa_handler = SIG_IGN; 2011.181Skamil sigemptyset(&sa.sa_mask); 2021.181Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 2031.94Skamil } 2041.94Skamil 2051.181Skamil DPRINTF("Before calling execve(2) from child\n"); 2061.181Skamil execlp("/bin/echo", "/bin/echo", NULL); 2071.181Skamil 2081.181Skamil /* NOTREACHED */ 2091.181Skamil FORKEE_ASSERTX(0 && "Not reached"); 2101.181Skamil } 2111.181Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2121.181Skamil 2131.181Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2141.181Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2151.94Skamil 2161.181Skamil validate_status_stopped(status, sigval); 2171.94Skamil 2181.181Skamil name[0] = CTL_KERN, 2191.181Skamil name[1] = KERN_PROC2, 2201.181Skamil name[2] = KERN_PROC_PID; 2211.181Skamil name[3] = getpid(); 2221.181Skamil name[4] = sizeof(kp); 2231.181Skamil name[5] = 1; 2241.59Skamil 2251.181Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 2261.59Skamil 2271.181Skamil if (masked) 2281.181Skamil kp_sigmask = kp.p_sigmask; 2291.59Skamil 2301.181Skamil if (ignored) 2311.181Skamil kp_sigignore = kp.p_sigignore; 2321.71Skamil 2331.181Skamil name[3] = getpid(); 2341.59Skamil 2351.181Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 2361.59Skamil 2371.181Skamil if (masked) { 2381.181Skamil DPRINTF("kp_sigmask=" 2391.181Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 2401.181Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 2411.181Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 2421.59Skamil 2431.181Skamil DPRINTF("kp.p_sigmask=" 2441.181Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 2451.181Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 2461.181Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 2471.59Skamil 2481.181Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 2491.181Skamil sizeof(kp_sigmask))); 2501.181Skamil } 2511.59Skamil 2521.181Skamil if (ignored) { 2531.181Skamil DPRINTF("kp_sigignore=" 2541.181Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 2551.181Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 2561.181Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 2571.59Skamil 2581.181Skamil DPRINTF("kp.p_sigignore=" 2591.181Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 2601.181Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 2611.181Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 2621.59Skamil 2631.181Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 2641.181Skamil sizeof(kp_sigignore))); 2651.181Skamil } 2661.59Skamil 2671.181Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 2681.181Skamil SYSCALL_REQUIRE( 2691.181Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 2701.59Skamil 2711.181Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2721.181Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 2731.181Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2741.181Skamil info.psi_siginfo.si_errno); 2751.71Skamil 2761.181Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 2771.181Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 2781.59Skamil 2791.181Skamil DPRINTF("Before resuming the child process where it left off and " 2801.181Skamil "without signal to be sent\n"); 2811.181Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2821.59Skamil 2831.181Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2841.181Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2851.94Skamil 2861.181Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2871.181Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 2881.94Skamil} 2891.94Skamil 2901.181Skamil#define TRACEME_VFORK_EXEC(test, masked, ignored) \ 2911.94SkamilATF_TC(test); \ 2921.94SkamilATF_TC_HEAD(test, tc) \ 2931.94Skamil{ \ 2941.94Skamil atf_tc_set_md_var(tc, "descr", \ 2951.181Skamil "Verify PT_TRACE_ME followed by exec(3) in a vfork(2)ed " \ 2961.181Skamil "child%s%s", masked ? " with masked signal" : "", \ 2971.181Skamil masked ? " with ignored signal" : ""); \ 2981.94Skamil} \ 2991.94Skamil \ 3001.94SkamilATF_TC_BODY(test, tc) \ 3011.94Skamil{ \ 3021.94Skamil \ 3031.181Skamil traceme_vfork_exec(masked, ignored); \ 3041.94Skamil} 3051.94Skamil 3061.181SkamilTRACEME_VFORK_EXEC(traceme_vfork_exec, false, false) 3071.181SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalmasked_exec, true, false) 3081.181SkamilTRACEME_VFORK_EXEC(traceme_vfork_signalignored_exec, false, true) 3091.59Skamil 3101.59Skamil/// ---------------------------------------------------------------------------- 3111.59Skamil 3121.59Skamil#if defined(TWAIT_HAVE_PID) 3131.59Skamilstatic void 3141.67Skamiltracer_sees_terminaton_before_the_parent_raw(bool notimeout, bool unrelated, 3151.67Skamil bool stopped) 3161.1Skamil{ 3171.51Skamil /* 3181.51Skamil * notimeout - disable timeout in await zombie function 3191.51Skamil * unrelated - attach from unrelated tracer reparented to initproc 3201.67Skamil * stopped - attach to a stopped process 3211.51Skamil */ 3221.1Skamil 3231.1Skamil struct msg_fds parent_tracee, parent_tracer; 3241.1Skamil const int exitval_tracee = 5; 3251.1Skamil const int exitval_tracer = 10; 3261.1Skamil pid_t tracee, tracer, wpid; 3271.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 3281.1Skamil#if defined(TWAIT_HAVE_STATUS) 3291.1Skamil int status; 3301.1Skamil#endif 3311.1Skamil 3321.67Skamil /* 3331.67Skamil * Only a subset of options are supported. 3341.67Skamil */ 3351.67Skamil ATF_REQUIRE((!notimeout && !unrelated && !stopped) || 3361.67Skamil (!notimeout && unrelated && !stopped) || 3371.67Skamil (notimeout && !unrelated && !stopped) || 3381.67Skamil (!notimeout && unrelated && stopped)); 3391.67Skamil 3401.13Schristos DPRINTF("Spawn tracee\n"); 3411.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 3421.1Skamil tracee = atf_utils_fork(); 3431.1Skamil if (tracee == 0) { 3441.67Skamil if (stopped) { 3451.67Skamil DPRINTF("Stop self PID %d\n", getpid()); 3461.67Skamil raise(SIGSTOP); 3471.67Skamil } 3481.67Skamil 3491.1Skamil // Wait for parent to let us exit 3501.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 3511.1Skamil _exit(exitval_tracee); 3521.1Skamil } 3531.1Skamil 3541.13Schristos DPRINTF("Spawn debugger\n"); 3551.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 3561.1Skamil tracer = atf_utils_fork(); 3571.1Skamil if (tracer == 0) { 3581.51Skamil if(unrelated) { 3591.51Skamil /* Fork again and drop parent to reattach to PID 1 */ 3601.51Skamil tracer = atf_utils_fork(); 3611.51Skamil if (tracer != 0) 3621.51Skamil _exit(exitval_tracer); 3631.51Skamil } 3641.51Skamil 3651.67Skamil if (stopped) { 3661.67Skamil DPRINTF("Await for a stopped parent PID %d\n", tracee); 3671.67Skamil await_stopped(tracee); 3681.67Skamil } 3691.67Skamil 3701.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 3711.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 3721.1Skamil 3731.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 3741.1Skamil FORKEE_REQUIRE_SUCCESS( 3751.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 3761.1Skamil 3771.1Skamil forkee_status_stopped(status, SIGSTOP); 3781.1Skamil 3791.1Skamil /* Resume tracee with PT_CONTINUE */ 3801.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 3811.1Skamil 3821.1Skamil /* Inform parent that tracer has attached to tracee */ 3831.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 3841.1Skamil 3851.1Skamil /* Wait for parent to tell use that tracee should have exited */ 3861.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 3871.1Skamil 3881.1Skamil /* Wait for tracee and assert that it exited */ 3891.1Skamil FORKEE_REQUIRE_SUCCESS( 3901.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 3911.1Skamil 3921.1Skamil forkee_status_exited(status, exitval_tracee); 3931.13Schristos DPRINTF("Tracee %d exited with %d\n", tracee, exitval_tracee); 3941.1Skamil 3951.13Schristos DPRINTF("Before exiting of the tracer process\n"); 3961.51Skamil _exit(unrelated ? 0 /* collect by initproc */ : exitval_tracer); 3971.51Skamil } 3981.51Skamil 3991.51Skamil if (unrelated) { 4001.51Skamil DPRINTF("Wait for the tracer process (direct child) to exit " 4011.51Skamil "calling %s()\n", TWAIT_FNAME); 4021.51Skamil TWAIT_REQUIRE_SUCCESS( 4031.51Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 4041.51Skamil 4051.51Skamil validate_status_exited(status, exitval_tracer); 4061.51Skamil 4071.51Skamil DPRINTF("Wait for the non-exited tracee process with %s()\n", 4081.51Skamil TWAIT_FNAME); 4091.51Skamil TWAIT_REQUIRE_SUCCESS( 4101.51Skamil wpid = TWAIT_GENERIC(tracee, NULL, WNOHANG), 0); 4111.1Skamil } 4121.1Skamil 4131.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 4141.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 4151.1Skamil 4161.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 4171.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 4181.1Skamil 4191.13Schristos DPRINTF("Detect that tracee is zombie\n"); 4201.51Skamil if (notimeout) 4211.26Skamil await_zombie_raw(tracee, 0); 4221.26Skamil else 4231.26Skamil await_zombie(tracee); 4241.1Skamil 4251.13Schristos DPRINTF("Assert that there is no status about tracee %d - " 4261.1Skamil "Tracer must detect zombie first - calling %s()\n", tracee, 4271.1Skamil TWAIT_FNAME); 4281.1Skamil TWAIT_REQUIRE_SUCCESS( 4291.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 4301.1Skamil 4311.51Skamil if (unrelated) { 4321.51Skamil DPRINTF("Resume the tracer and let it detect exited tracee\n"); 4331.51Skamil PARENT_TO_CHILD("Message 2", parent_tracer, msg); 4341.51Skamil } else { 4351.51Skamil DPRINTF("Tell the tracer child should have exited\n"); 4361.51Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 4371.51Skamil DPRINTF("Wait for tracer to finish its job and exit - calling " 4381.59Skamil "%s()\n", TWAIT_FNAME); 4391.51Skamil 4401.51Skamil DPRINTF("Wait from tracer child to complete waiting for " 4411.59Skamil "tracee\n"); 4421.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 4431.51Skamil tracer); 4441.1Skamil 4451.51Skamil validate_status_exited(status, exitval_tracer); 4461.51Skamil } 4471.1Skamil 4481.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 4491.1Skamil TWAIT_FNAME); 4501.51Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 4511.1Skamil 4521.1Skamil validate_status_exited(status, exitval_tracee); 4531.1Skamil 4541.1Skamil msg_close(&parent_tracer); 4551.1Skamil msg_close(&parent_tracee); 4561.1Skamil} 4571.26Skamil 4581.51SkamilATF_TC(tracer_sees_terminaton_before_the_parent); 4591.51SkamilATF_TC_HEAD(tracer_sees_terminaton_before_the_parent, tc) 4601.51Skamil{ 4611.51Skamil atf_tc_set_md_var(tc, "descr", 4621.51Skamil "Assert that tracer sees process termination before the parent"); 4631.51Skamil} 4641.51Skamil 4651.51SkamilATF_TC_BODY(tracer_sees_terminaton_before_the_parent, tc) 4661.26Skamil{ 4671.26Skamil 4681.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, false, false); 4691.26Skamil} 4701.26Skamil 4711.51SkamilATF_TC(tracer_sysctl_lookup_without_duplicates); 4721.51SkamilATF_TC_HEAD(tracer_sysctl_lookup_without_duplicates, tc) 4731.1Skamil{ 4741.164Skamil atf_tc_set_md_var(tc, "timeout", "15"); 4751.1Skamil atf_tc_set_md_var(tc, "descr", 4761.51Skamil "Assert that await_zombie() in attach1 always finds a single " 4771.51Skamil "process and no other error is reported"); 4781.1Skamil} 4791.1Skamil 4801.51SkamilATF_TC_BODY(tracer_sysctl_lookup_without_duplicates, tc) 4811.1Skamil{ 4821.51Skamil time_t start, end; 4831.51Skamil double diff; 4841.51Skamil unsigned long N = 0; 4851.1Skamil 4861.51Skamil /* 4871.51Skamil * Reuse this test with tracer_sees_terminaton_before_the_parent_raw(). 4881.51Skamil * This test body isn't specific to this race, however it's just good 4891.51Skamil * enough for this purposes, no need to invent a dedicated code flow. 4901.51Skamil */ 4911.1Skamil 4921.51Skamil start = time(NULL); 4931.51Skamil while (true) { 4941.51Skamil DPRINTF("Step: %lu\n", N); 4951.67Skamil tracer_sees_terminaton_before_the_parent_raw(true, false, 4961.67Skamil false); 4971.51Skamil end = time(NULL); 4981.51Skamil diff = difftime(end, start); 4991.51Skamil if (diff >= 5.0) 5001.51Skamil break; 5011.51Skamil ++N; 5021.1Skamil } 5031.51Skamil DPRINTF("Iterations: %lu\n", N); 5041.51Skamil} 5051.1Skamil 5061.51SkamilATF_TC(unrelated_tracer_sees_terminaton_before_the_parent); 5071.51SkamilATF_TC_HEAD(unrelated_tracer_sees_terminaton_before_the_parent, tc) 5081.51Skamil{ 5091.51Skamil atf_tc_set_md_var(tc, "descr", 5101.51Skamil "Assert that tracer sees process termination before the parent"); 5111.51Skamil} 5121.1Skamil 5131.51SkamilATF_TC_BODY(unrelated_tracer_sees_terminaton_before_the_parent, tc) 5141.51Skamil{ 5151.1Skamil 5161.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, false); 5171.67Skamil} 5181.67Skamil 5191.67SkamilATF_TC(tracer_attach_to_unrelated_stopped_process); 5201.67SkamilATF_TC_HEAD(tracer_attach_to_unrelated_stopped_process, tc) 5211.67Skamil{ 5221.67Skamil atf_tc_set_md_var(tc, "descr", 5231.67Skamil "Assert that tracer can attach to an unrelated stopped process"); 5241.67Skamil} 5251.67Skamil 5261.67SkamilATF_TC_BODY(tracer_attach_to_unrelated_stopped_process, tc) 5271.67Skamil{ 5281.67Skamil 5291.67Skamil tracer_sees_terminaton_before_the_parent_raw(false, true, true); 5301.1Skamil} 5311.1Skamil#endif 5321.1Skamil 5331.51Skamil/// ---------------------------------------------------------------------------- 5341.51Skamil 5351.66Skamilstatic void 5361.66Skamilparent_attach_to_its_child(bool stopped) 5371.1Skamil{ 5381.1Skamil struct msg_fds parent_tracee; 5391.1Skamil const int exitval_tracee = 5; 5401.1Skamil pid_t tracee, wpid; 5411.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 5421.1Skamil#if defined(TWAIT_HAVE_STATUS) 5431.1Skamil int status; 5441.1Skamil#endif 5451.1Skamil 5461.13Schristos DPRINTF("Spawn tracee\n"); 5471.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 5481.1Skamil tracee = atf_utils_fork(); 5491.1Skamil if (tracee == 0) { 5501.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 5511.13Schristos DPRINTF("Parent should now attach to tracee\n"); 5521.1Skamil 5531.66Skamil if (stopped) { 5541.66Skamil DPRINTF("Stop self PID %d\n", getpid()); 5551.66Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 5561.66Skamil } 5571.66Skamil 5581.1Skamil CHILD_FROM_PARENT("Message 2", parent_tracee, msg); 5591.1Skamil /* Wait for message from the parent */ 5601.1Skamil _exit(exitval_tracee); 5611.1Skamil } 5621.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 5631.57Skamil 5641.66Skamil if (stopped) { 5651.66Skamil DPRINTF("Await for a stopped tracee PID %d\n", tracee); 5661.66Skamil await_stopped(tracee); 5671.66Skamil } 5681.66Skamil 5691.13Schristos DPRINTF("Before calling PT_ATTACH for tracee %d\n", tracee); 5701.13Schristos SYSCALL_REQUIRE(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 5711.1Skamil 5721.13Schristos DPRINTF("Wait for the stopped tracee process with %s()\n", 5731.1Skamil TWAIT_FNAME); 5741.1Skamil TWAIT_REQUIRE_SUCCESS( 5751.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 5761.1Skamil 5771.1Skamil validate_status_stopped(status, SIGSTOP); 5781.1Skamil 5791.13Schristos DPRINTF("Resume tracee with PT_CONTINUE\n"); 5801.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 5811.1Skamil 5821.13Schristos DPRINTF("Let the tracee exit now\n"); 5831.1Skamil PARENT_TO_CHILD("Message 2", parent_tracee, msg); 5841.1Skamil 5851.13Schristos DPRINTF("Wait for tracee to exit with %s()\n", TWAIT_FNAME); 5861.1Skamil TWAIT_REQUIRE_SUCCESS( 5871.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 5881.1Skamil 5891.1Skamil validate_status_exited(status, exitval_tracee); 5901.1Skamil 5911.13Schristos DPRINTF("Before calling %s() for tracee\n", TWAIT_FNAME); 5921.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 5931.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0)); 5941.1Skamil 5951.1Skamil msg_close(&parent_tracee); 5961.1Skamil} 5971.1Skamil 5981.66SkamilATF_TC(parent_attach_to_its_child); 5991.66SkamilATF_TC_HEAD(parent_attach_to_its_child, tc) 6001.66Skamil{ 6011.66Skamil atf_tc_set_md_var(tc, "descr", 6021.66Skamil "Assert that tracer parent can PT_ATTACH to its child"); 6031.66Skamil} 6041.66Skamil 6051.66SkamilATF_TC_BODY(parent_attach_to_its_child, tc) 6061.66Skamil{ 6071.66Skamil 6081.66Skamil parent_attach_to_its_child(false); 6091.66Skamil} 6101.66Skamil 6111.66SkamilATF_TC(parent_attach_to_its_stopped_child); 6121.66SkamilATF_TC_HEAD(parent_attach_to_its_stopped_child, tc) 6131.66Skamil{ 6141.66Skamil atf_tc_set_md_var(tc, "descr", 6151.66Skamil "Assert that tracer parent can PT_ATTACH to its stopped child"); 6161.66Skamil} 6171.66Skamil 6181.66SkamilATF_TC_BODY(parent_attach_to_its_stopped_child, tc) 6191.66Skamil{ 6201.66Skamil 6211.66Skamil parent_attach_to_its_child(true); 6221.66Skamil} 6231.66Skamil 6241.51Skamil/// ---------------------------------------------------------------------------- 6251.51Skamil 6261.65Skamilstatic void 6271.65Skamilchild_attach_to_its_parent(bool stopped) 6281.1Skamil{ 6291.1Skamil struct msg_fds parent_tracee; 6301.1Skamil const int exitval_tracer = 5; 6311.1Skamil pid_t tracer, wpid; 6321.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 6331.1Skamil#if defined(TWAIT_HAVE_STATUS) 6341.1Skamil int status; 6351.1Skamil#endif 6361.1Skamil 6371.13Schristos DPRINTF("Spawn tracer\n"); 6381.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 6391.1Skamil tracer = atf_utils_fork(); 6401.1Skamil if (tracer == 0) { 6411.1Skamil /* Wait for message from the parent */ 6421.1Skamil CHILD_FROM_PARENT("Message 1", parent_tracee, msg); 6431.1Skamil 6441.65Skamil if (stopped) { 6451.65Skamil DPRINTF("Await for a stopped parent PID %d\n", 6461.65Skamil getppid()); 6471.65Skamil await_stopped(getppid()); 6481.65Skamil } 6491.65Skamil 6501.13Schristos DPRINTF("Attach to parent PID %d with PT_ATTACH from child\n", 6511.1Skamil getppid()); 6521.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, getppid(), NULL, 0) != -1); 6531.1Skamil 6541.13Schristos DPRINTF("Wait for the stopped parent process with %s()\n", 6551.1Skamil TWAIT_FNAME); 6561.1Skamil FORKEE_REQUIRE_SUCCESS( 6571.1Skamil wpid = TWAIT_GENERIC(getppid(), &status, 0), getppid()); 6581.1Skamil 6591.1Skamil forkee_status_stopped(status, SIGSTOP); 6601.1Skamil 6611.13Schristos DPRINTF("Resume parent with PT_DETACH\n"); 6621.1Skamil FORKEE_ASSERT(ptrace(PT_DETACH, getppid(), (void *)1, 0) 6631.1Skamil != -1); 6641.1Skamil 6651.1Skamil /* Tell parent we are ready */ 6661.1Skamil CHILD_TO_PARENT("Message 1", parent_tracee, msg); 6671.1Skamil 6681.1Skamil _exit(exitval_tracer); 6691.1Skamil } 6701.1Skamil 6711.13Schristos DPRINTF("Wait for the tracer to become ready\n"); 6721.1Skamil PARENT_TO_CHILD("Message 1", parent_tracee, msg); 6731.65Skamil 6741.65Skamil if (stopped) { 6751.65Skamil DPRINTF("Stop self PID %d\n", getpid()); 6761.65Skamil SYSCALL_REQUIRE(raise(SIGSTOP) != -1); 6771.65Skamil } 6781.65Skamil 6791.13Schristos DPRINTF("Allow the tracer to exit now\n"); 6801.1Skamil PARENT_FROM_CHILD("Message 1", parent_tracee, msg); 6811.1Skamil 6821.13Schristos DPRINTF("Wait for tracer to exit with %s()\n", TWAIT_FNAME); 6831.1Skamil TWAIT_REQUIRE_SUCCESS( 6841.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0), tracer); 6851.1Skamil 6861.1Skamil validate_status_exited(status, exitval_tracer); 6871.1Skamil 6881.13Schristos DPRINTF("Before calling %s() for tracer\n", TWAIT_FNAME); 6891.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, 6901.1Skamil wpid = TWAIT_GENERIC(tracer, &status, 0)); 6911.1Skamil 6921.1Skamil msg_close(&parent_tracee); 6931.1Skamil} 6941.1Skamil 6951.65SkamilATF_TC(child_attach_to_its_parent); 6961.65SkamilATF_TC_HEAD(child_attach_to_its_parent, tc) 6971.65Skamil{ 6981.65Skamil atf_tc_set_md_var(tc, "descr", 6991.65Skamil "Assert that tracer child can PT_ATTACH to its parent"); 7001.65Skamil} 7011.65Skamil 7021.65SkamilATF_TC_BODY(child_attach_to_its_parent, tc) 7031.65Skamil{ 7041.65Skamil 7051.65Skamil child_attach_to_its_parent(false); 7061.65Skamil} 7071.65Skamil 7081.65SkamilATF_TC(child_attach_to_its_stopped_parent); 7091.65SkamilATF_TC_HEAD(child_attach_to_its_stopped_parent, tc) 7101.65Skamil{ 7111.65Skamil atf_tc_set_md_var(tc, "descr", 7121.65Skamil "Assert that tracer child can PT_ATTACH to its stopped parent"); 7131.65Skamil} 7141.65Skamil 7151.65SkamilATF_TC_BODY(child_attach_to_its_stopped_parent, tc) 7161.65Skamil{ 7171.65Skamil /* 7181.65Skamil * The ATF framework (atf-run) does not tolerate raise(SIGSTOP), as 7191.65Skamil * this causes a pipe (established from atf-run) to be broken. 7201.65Skamil * atf-run uses this mechanism to monitor whether a test is alive. 7211.65Skamil * 7221.65Skamil * As a workaround spawn this test as a subprocess. 7231.65Skamil */ 7241.65Skamil 7251.65Skamil const int exitval = 15; 7261.65Skamil pid_t child, wpid; 7271.65Skamil#if defined(TWAIT_HAVE_STATUS) 7281.65Skamil int status; 7291.65Skamil#endif 7301.65Skamil 7311.65Skamil SYSCALL_REQUIRE((child = fork()) != -1); 7321.65Skamil if (child == 0) { 7331.65Skamil child_attach_to_its_parent(true); 7341.65Skamil _exit(exitval); 7351.65Skamil } else { 7361.65Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 7371.65Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 7381.65Skamil 7391.65Skamil validate_status_exited(status, exitval); 7401.65Skamil 7411.65Skamil DPRINTF("Before calling %s() for the exited child\n", TWAIT_FNAME); 7421.65Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 7431.65Skamil } 7441.65Skamil} 7451.65Skamil 7461.51Skamil/// ---------------------------------------------------------------------------- 7471.51Skamil 7481.1Skamil#if defined(TWAIT_HAVE_PID) 7491.1Skamil 7501.51Skamilenum tracee_sees_its_original_parent_type { 7511.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 7521.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 7531.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS 7541.51Skamil}; 7551.51Skamil 7561.51Skamilstatic void 7571.51Skamiltracee_sees_its_original_parent(enum tracee_sees_its_original_parent_type type) 7581.1Skamil{ 7591.1Skamil struct msg_fds parent_tracer, parent_tracee; 7601.1Skamil const int exitval_tracee = 5; 7611.1Skamil const int exitval_tracer = 10; 7621.1Skamil pid_t parent, tracee, tracer, wpid; 7631.1Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 7641.1Skamil#if defined(TWAIT_HAVE_STATUS) 7651.1Skamil int status; 7661.1Skamil#endif 7671.51Skamil /* sysctl(3) - kinfo_proc2 */ 7681.51Skamil int name[CTL_MAXNAME]; 7691.51Skamil struct kinfo_proc2 kp; 7701.51Skamil size_t len = sizeof(kp); 7711.51Skamil unsigned int namelen; 7721.51Skamil 7731.51Skamil /* procfs - status */ 7741.51Skamil FILE *fp; 7751.51Skamil struct stat st; 7761.51Skamil const char *fname = "/proc/curproc/status"; 7771.51Skamil char s_executable[MAXPATHLEN]; 7781.51Skamil int s_pid, s_ppid; 7791.51Skamil int rv; 7801.51Skamil 7811.51Skamil if (type == TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS) { 7821.61Skre SYSCALL_REQUIRE( 7831.61Skre (rv = stat(fname, &st)) == 0 || (errno == ENOENT)); 7841.61Skre if (rv != 0) 7851.51Skamil atf_tc_skip("/proc/curproc/status not found"); 7861.51Skamil } 7871.1Skamil 7881.13Schristos DPRINTF("Spawn tracee\n"); 7891.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 7901.13Schristos SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 7911.1Skamil tracee = atf_utils_fork(); 7921.1Skamil if (tracee == 0) { 7931.1Skamil parent = getppid(); 7941.1Skamil 7951.1Skamil /* Emit message to the parent */ 7961.1Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 7971.1Skamil CHILD_FROM_PARENT("exit tracee", parent_tracee, msg); 7981.1Skamil 7991.51Skamil switch (type) { 8001.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID: 8011.51Skamil FORKEE_ASSERT_EQ(parent, getppid()); 8021.51Skamil break; 8031.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2: 8041.51Skamil namelen = 0; 8051.51Skamil name[namelen++] = CTL_KERN; 8061.51Skamil name[namelen++] = KERN_PROC2; 8071.51Skamil name[namelen++] = KERN_PROC_PID; 8081.51Skamil name[namelen++] = getpid(); 8091.51Skamil name[namelen++] = len; 8101.51Skamil name[namelen++] = 1; 8111.51Skamil 8121.61Skre FORKEE_ASSERT_EQ( 8131.61Skre sysctl(name, namelen, &kp, &len, NULL, 0), 0); 8141.51Skamil FORKEE_ASSERT_EQ(parent, kp.p_ppid); 8151.51Skamil break; 8161.51Skamil case TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS: 8171.51Skamil /* 8181.51Skamil * Format: 8191.51Skamil * EXECUTABLE PID PPID ... 8201.51Skamil */ 8211.51Skamil FORKEE_ASSERT((fp = fopen(fname, "r")) != NULL); 8221.51Skamil fscanf(fp, "%s %d %d", s_executable, &s_pid, &s_ppid); 8231.51Skamil FORKEE_ASSERT_EQ(fclose(fp), 0); 8241.51Skamil FORKEE_ASSERT_EQ(parent, s_ppid); 8251.51Skamil break; 8261.51Skamil } 8271.1Skamil 8281.1Skamil _exit(exitval_tracee); 8291.1Skamil } 8301.13Schristos DPRINTF("Wait for child to record its parent identifier (pid)\n"); 8311.1Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 8321.1Skamil 8331.13Schristos DPRINTF("Spawn debugger\n"); 8341.1Skamil tracer = atf_utils_fork(); 8351.1Skamil if (tracer == 0) { 8361.1Skamil /* No IPC to communicate with the child */ 8371.13Schristos DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 8381.1Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 8391.1Skamil 8401.1Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 8411.1Skamil FORKEE_REQUIRE_SUCCESS( 8421.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 8431.1Skamil 8441.1Skamil forkee_status_stopped(status, SIGSTOP); 8451.1Skamil 8461.1Skamil /* Resume tracee with PT_CONTINUE */ 8471.1Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 8481.1Skamil 8491.1Skamil /* Inform parent that tracer has attached to tracee */ 8501.1Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 8511.1Skamil 8521.1Skamil /* Wait for parent to tell use that tracee should have exited */ 8531.1Skamil CHILD_FROM_PARENT("wait for tracee exit", parent_tracer, msg); 8541.1Skamil 8551.1Skamil /* Wait for tracee and assert that it exited */ 8561.1Skamil FORKEE_REQUIRE_SUCCESS( 8571.1Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 8581.1Skamil 8591.1Skamil forkee_status_exited(status, exitval_tracee); 8601.1Skamil 8611.13Schristos DPRINTF("Before exiting of the tracer process\n"); 8621.1Skamil _exit(exitval_tracer); 8631.1Skamil } 8641.1Skamil 8651.13Schristos DPRINTF("Wait for the tracer to attach to the tracee\n"); 8661.1Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 8671.1Skamil 8681.13Schristos DPRINTF("Resume the tracee and let it exit\n"); 8691.1Skamil PARENT_TO_CHILD("exit tracee", parent_tracee, msg); 8701.1Skamil 8711.13Schristos DPRINTF("Detect that tracee is zombie\n"); 8721.1Skamil await_zombie(tracee); 8731.1Skamil 8741.13Schristos DPRINTF("Assert that there is no status about tracee - " 8751.1Skamil "Tracer must detect zombie first - calling %s()\n", TWAIT_FNAME); 8761.1Skamil TWAIT_REQUIRE_SUCCESS( 8771.1Skamil wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 0); 8781.1Skamil 8791.13Schristos DPRINTF("Tell the tracer child should have exited\n"); 8801.1Skamil PARENT_TO_CHILD("wait for tracee exit", parent_tracer, msg); 8811.1Skamil 8821.13Schristos DPRINTF("Wait from tracer child to complete waiting for tracee\n"); 8831.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 8841.1Skamil tracer); 8851.1Skamil 8861.1Skamil validate_status_exited(status, exitval_tracer); 8871.1Skamil 8881.13Schristos DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 8891.1Skamil TWAIT_FNAME); 8901.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 8911.1Skamil tracee); 8921.1Skamil 8931.1Skamil validate_status_exited(status, exitval_tracee); 8941.1Skamil 8951.1Skamil msg_close(&parent_tracer); 8961.1Skamil msg_close(&parent_tracee); 8971.1Skamil} 8981.1Skamil 8991.61Skre#define TRACEE_SEES_ITS_ORIGINAL_PARENT(test, type, descr) \ 9001.61SkreATF_TC(test); \ 9011.61SkreATF_TC_HEAD(test, tc) \ 9021.61Skre{ \ 9031.61Skre atf_tc_set_md_var(tc, "descr", \ 9041.61Skre "Assert that tracee sees its original parent when being traced " \ 9051.61Skre "(check " descr ")"); \ 9061.61Skre} \ 9071.61Skre \ 9081.61SkreATF_TC_BODY(test, tc) \ 9091.61Skre{ \ 9101.61Skre \ 9111.61Skre tracee_sees_its_original_parent(type); \ 9121.1Skamil} 9131.1Skamil 9141.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 9151.51Skamil tracee_sees_its_original_parent_getppid, 9161.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_GETPPID, 9171.51Skamil "getppid(2)"); 9181.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 9191.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2, 9201.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_SYSCTL_KINFO_PROC2, 9211.51Skamil "sysctl(3) and kinfo_proc2"); 9221.51SkamilTRACEE_SEES_ITS_ORIGINAL_PARENT( 9231.51Skamil tracee_sees_its_original_parent_procfs_status, 9241.51Skamil TRACEE_SEES_ITS_ORIGINAL_PARENT_PROCFS_STATUS, 9251.51Skamil "the status file in procfs"); 9261.1Skamil#endif 9271.1Skamil 9281.51Skamil/// ---------------------------------------------------------------------------- 9291.1Skamil 9301.180Skamilstatic int lwpinfo_thread_sigmask[] = {SIGXCPU, SIGPIPE, SIGALRM, SIGURG}; 9311.180Skamil 9321.180Skamilstatic pthread_mutex_t lwpinfo_thread_mtx = PTHREAD_MUTEX_INITIALIZER; 9331.180Skamilstatic pthread_cond_t lwpinfo_thread_cnd = PTHREAD_COND_INITIALIZER; 9341.180Skamilstatic volatile size_t lwpinfo_thread_done; 9351.180Skamil 9361.180Skamilstatic void * 9371.180Skamillwpinfo_thread(void *arg) 9381.180Skamil{ 9391.180Skamil sigset_t s; 9401.180Skamil volatile void **tcb; 9411.180Skamil 9421.180Skamil tcb = (volatile void **)arg; 9431.180Skamil 9441.180Skamil *tcb = _lwp_getprivate(); 9451.180Skamil DPRINTF("Storing tcb[] = %p from thread %d\n", *tcb, _lwp_self()); 9461.180Skamil 9471.180Skamil pthread_setname_np(pthread_self(), "thread %d", 9481.180Skamil (void *)(intptr_t)_lwp_self()); 9491.180Skamil 9501.180Skamil sigemptyset(&s); 9511.180Skamil pthread_mutex_lock(&lwpinfo_thread_mtx); 9521.180Skamil sigaddset(&s, lwpinfo_thread_sigmask[lwpinfo_thread_done]); 9531.180Skamil lwpinfo_thread_done++; 9541.180Skamil pthread_sigmask(SIG_BLOCK, &s, NULL); 9551.180Skamil pthread_cond_signal(&lwpinfo_thread_cnd); 9561.180Skamil pthread_mutex_unlock(&lwpinfo_thread_mtx); 9571.180Skamil 9581.180Skamil return infinite_thread(NULL); 9591.180Skamil} 9601.180Skamil 9611.28Skamilstatic void 9621.180Skamiltraceme_lwpinfo(const size_t threads, const char *iter) 9631.1Skamil{ 9641.1Skamil const int sigval = SIGSTOP; 9651.180Skamil const int sigval2 = SIGINT; 9661.180Skamil pid_t child, wpid; 9671.1Skamil#if defined(TWAIT_HAVE_STATUS) 9681.1Skamil int status; 9691.1Skamil#endif 9701.180Skamil struct ptrace_lwpinfo lwp = {0, 0}; 9711.180Skamil struct ptrace_lwpstatus lwpstatus = {0}; 9721.180Skamil struct ptrace_siginfo info; 9731.180Skamil void *private; 9741.180Skamil char *name; 9751.180Skamil char namebuf[PL_LNAMELEN]; 9761.180Skamil volatile void *tcb[4]; 9771.180Skamil bool found; 9781.180Skamil sigset_t s; 9791.180Skamil 9801.180Skamil /* Maximum number of supported threads in this test */ 9811.180Skamil pthread_t t[__arraycount(tcb) - 1]; 9821.180Skamil size_t n, m; 9831.180Skamil int rv; 9841.180Skamil size_t bytes_read; 9851.180Skamil 9861.180Skamil struct ptrace_io_desc io; 9871.180Skamil sigset_t sigmask; 9881.1Skamil 9891.180Skamil ATF_REQUIRE(__arraycount(t) >= threads); 9901.180Skamil memset(tcb, 0, sizeof(tcb)); 9911.124Skamil 9921.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 9931.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 9941.1Skamil if (child == 0) { 9951.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 9961.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 9971.1Skamil 9981.180Skamil tcb[0] = _lwp_getprivate(); 9991.180Skamil DPRINTF("Storing tcb[0] = %p\n", tcb[0]); 10001.180Skamil 10011.180Skamil pthread_setname_np(pthread_self(), "thread %d", 10021.180Skamil (void *)(intptr_t)_lwp_self()); 10031.180Skamil 10041.180Skamil sigemptyset(&s); 10051.180Skamil sigaddset(&s, lwpinfo_thread_sigmask[lwpinfo_thread_done]); 10061.180Skamil pthread_sigmask(SIG_BLOCK, &s, NULL); 10071.180Skamil 10081.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 10091.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 10101.1Skamil 10111.180Skamil for (n = 0; n < threads; n++) { 10121.180Skamil rv = pthread_create(&t[n], NULL, lwpinfo_thread, 10131.180Skamil &tcb[n + 1]); 10141.180Skamil FORKEE_ASSERT(rv == 0); 10151.180Skamil } 10161.1Skamil 10171.180Skamil pthread_mutex_lock(&lwpinfo_thread_mtx); 10181.180Skamil while (lwpinfo_thread_done < threads) { 10191.180Skamil pthread_cond_wait(&lwpinfo_thread_cnd, 10201.180Skamil &lwpinfo_thread_mtx); 10211.124Skamil } 10221.180Skamil pthread_mutex_unlock(&lwpinfo_thread_mtx); 10231.1Skamil 10241.180Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval2)); 10251.180Skamil FORKEE_ASSERT(raise(sigval2) == 0); 10261.1Skamil 10271.180Skamil /* NOTREACHED */ 10281.180Skamil FORKEE_ASSERTX(0 && "Not reached"); 10291.1Skamil } 10301.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 10311.1Skamil 10321.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10331.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10341.1Skamil 10351.1Skamil validate_status_stopped(status, sigval); 10361.1Skamil 10371.180Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 10381.180Skamil SYSCALL_REQUIRE( 10391.180Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 10401.1Skamil 10411.180Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 10421.180Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 10431.180Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 10441.180Skamil info.psi_siginfo.si_errno); 10451.1Skamil 10461.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 10471.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 10481.1Skamil 10491.180Skamil if (strstr(iter, "LWPINFO") != NULL) { 10501.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 10511.180Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) 10521.180Skamil != -1); 10531.1Skamil 10541.180Skamil DPRINTF("Assert that there exists a single thread only\n"); 10551.180Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 10561.1Skamil 10571.180Skamil DPRINTF("Assert that lwp thread %d received event " 10581.180Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 10591.180Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 10601.1Skamil 10611.180Skamil if (strstr(iter, "LWPSTATUS") != NULL) { 10621.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPSTATUS " 10631.180Skamil "for child\n"); 10641.180Skamil lwpstatus.pl_lwpid = lwp.pl_lwpid; 10651.180Skamil SYSCALL_REQUIRE(ptrace(PT_LWPSTATUS, child, &lwpstatus, 10661.180Skamil sizeof(lwpstatus)) != -1); 10671.30Skamil } 10681.30Skamil 10691.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 10701.180Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) 10711.180Skamil != -1); 10721.29Skamil 10731.180Skamil DPRINTF("Assert that there exists a single thread only\n"); 10741.180Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 10751.180Skamil } else { 10761.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for child\n"); 10771.180Skamil SYSCALL_REQUIRE(ptrace(PT_LWPNEXT, child, &lwpstatus, 10781.180Skamil sizeof(lwpstatus)) != -1); 10791.29Skamil 10801.180Skamil DPRINTF("Assert that there exists a single thread only %d\n", lwpstatus.pl_lwpid); 10811.180Skamil ATF_REQUIRE(lwpstatus.pl_lwpid > 0); 10821.30Skamil 10831.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for child\n"); 10841.180Skamil SYSCALL_REQUIRE(ptrace(PT_LWPNEXT, child, &lwpstatus, 10851.180Skamil sizeof(lwpstatus)) != -1); 10861.30Skamil 10871.180Skamil DPRINTF("Assert that there exists a single thread only\n"); 10881.180Skamil ATF_REQUIRE_EQ(lwpstatus.pl_lwpid, 0); 10891.30Skamil } 10901.29Skamil 10911.13Schristos DPRINTF("Before resuming the child process where it left off and " 10921.1Skamil "without signal to be sent\n"); 10931.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 10941.1Skamil 10951.180Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 10961.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 10971.1Skamil 10981.180Skamil validate_status_stopped(status, sigval2); 10991.180Skamil 11001.180Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child"); 11011.180Skamil SYSCALL_REQUIRE( 11021.180Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 11031.180Skamil 11041.180Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 11051.180Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 11061.180Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 11071.180Skamil info.psi_siginfo.si_errno); 11081.1Skamil 11091.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval2); 11101.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 11111.28Skamil 11121.180Skamil memset(&lwp, 0, sizeof(lwp)); 11131.180Skamil memset(&lwpstatus, 0, sizeof(lwpstatus)); 11141.32Skamil 11151.180Skamil memset(&io, 0, sizeof(io)); 11161.1Skamil 11171.180Skamil bytes_read = 0; 11181.180Skamil io.piod_op = PIOD_READ_D; 11191.180Skamil io.piod_len = sizeof(tcb); 11201.125Skamil 11211.180Skamil do { 11221.180Skamil io.piod_addr = (char *)&tcb + bytes_read; 11231.180Skamil io.piod_offs = io.piod_addr; 11241.124Skamil 11251.180Skamil rv = ptrace(PT_IO, child, &io, sizeof(io)); 11261.180Skamil ATF_REQUIRE(rv != -1 && io.piod_len != 0); 11271.31Skamil 11281.180Skamil bytes_read += io.piod_len; 11291.180Skamil io.piod_len = sizeof(tcb) - bytes_read; 11301.180Skamil } while (bytes_read < sizeof(tcb)); 11311.149Skamil 11321.180Skamil for (n = 0; n <= threads; n++) { 11331.180Skamil if (strstr(iter, "LWPINFO") != NULL) { 11341.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 11351.180Skamil "child\n"); 11361.180Skamil SYSCALL_REQUIRE( 11371.180Skamil ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) != -1); 11381.180Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 11391.149Skamil 11401.180Skamil DPRINTF("Assert that the thread exists\n"); 11411.180Skamil ATF_REQUIRE(lwp.pl_lwpid > 0); 11421.149Skamil 11431.180Skamil DPRINTF("Assert that lwp thread %d received expected " 11441.180Skamil "event\n", lwp.pl_lwpid); 11451.180Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 11461.180Skamil info.psi_lwpid == lwp.pl_lwpid ? 11471.180Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 11481.149Skamil 11491.180Skamil if (strstr(iter, "LWPSTATUS") != NULL) { 11501.180Skamil DPRINTF("Before calling ptrace(2) with " 11511.180Skamil "PT_LWPSTATUS for child\n"); 11521.180Skamil lwpstatus.pl_lwpid = lwp.pl_lwpid; 11531.180Skamil SYSCALL_REQUIRE(ptrace(PT_LWPSTATUS, child, 11541.180Skamil &lwpstatus, sizeof(lwpstatus)) != -1); 11551.149Skamil 11561.180Skamil goto check_lwpstatus; 11571.180Skamil } 11581.149Skamil } else { 11591.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for " 11601.180Skamil "child\n"); 11611.180Skamil SYSCALL_REQUIRE( 11621.180Skamil ptrace(PT_LWPNEXT, child, &lwpstatus, 11631.180Skamil sizeof(lwpstatus)) != -1); 11641.180Skamil DPRINTF("LWP=%d\n", lwpstatus.pl_lwpid); 11651.149Skamil 11661.180Skamil DPRINTF("Assert that the thread exists\n"); 11671.180Skamil ATF_REQUIRE(lwpstatus.pl_lwpid > 0); 11681.149Skamil 11691.180Skamil check_lwpstatus: 11701.149Skamil 11711.180Skamil if (strstr(iter, "pl_sigmask") != NULL) { 11721.180Skamil sigmask = lwpstatus.pl_sigmask; 11731.149Skamil 11741.180Skamil DPRINTF("Retrieved sigmask: " 11751.180Skamil "%02x%02x%02x%02x\n", 11761.180Skamil sigmask.__bits[0], sigmask.__bits[1], 11771.180Skamil sigmask.__bits[2], sigmask.__bits[3]); 11781.149Skamil 11791.180Skamil found = false; 11801.180Skamil for (m = 0; 11811.180Skamil m < __arraycount(lwpinfo_thread_sigmask); 11821.180Skamil m++) { 11831.180Skamil if (sigismember(&sigmask, 11841.180Skamil lwpinfo_thread_sigmask[m])) { 11851.180Skamil found = true; 11861.180Skamil lwpinfo_thread_sigmask[m] = 0; 11871.180Skamil break; 11881.180Skamil } 11891.180Skamil } 11901.180Skamil ATF_REQUIRE(found == true); 11911.180Skamil } else if (strstr(iter, "pl_name") != NULL) { 11921.180Skamil name = lwpstatus.pl_name; 11931.149Skamil 11941.180Skamil DPRINTF("Retrieved thread name: " 11951.180Skamil "%s\n", name); 11961.149Skamil 11971.180Skamil snprintf(namebuf, sizeof namebuf, "thread %d", 11981.180Skamil lwpstatus.pl_lwpid); 11991.149Skamil 12001.180Skamil ATF_REQUIRE(strcmp(name, namebuf) == 0); 12011.180Skamil } else if (strstr(iter, "pl_private") != NULL) { 12021.180Skamil private = lwpstatus.pl_private; 12031.149Skamil 12041.180Skamil DPRINTF("Retrieved thread private pointer: " 12051.180Skamil "%p\n", private); 12061.149Skamil 12071.180Skamil found = false; 12081.180Skamil for (m = 0; m < __arraycount(tcb); m++) { 12091.180Skamil DPRINTF("Comparing %p and %p\n", 12101.180Skamil private, tcb[m]); 12111.180Skamil if (private == tcb[m]) { 12121.180Skamil found = true; 12131.180Skamil break; 12141.180Skamil } 12151.180Skamil } 12161.180Skamil ATF_REQUIRE(found == true); 12171.180Skamil } 12181.180Skamil } 12191.180Skamil } 12201.149Skamil 12211.180Skamil if (strstr(iter, "LWPINFO") != NULL) { 12221.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 12231.180Skamil "child\n"); 12241.180Skamil SYSCALL_REQUIRE(ptrace(PT_LWPINFO, child, &lwp, sizeof(lwp)) 12251.180Skamil != -1); 12261.180Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 12271.149Skamil 12281.180Skamil DPRINTF("Assert that there are no more threads\n"); 12291.180Skamil ATF_REQUIRE_EQ(lwp.pl_lwpid, 0); 12301.180Skamil } else { 12311.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPNEXT for child\n"); 12321.180Skamil SYSCALL_REQUIRE(ptrace(PT_LWPNEXT, child, &lwpstatus, 12331.180Skamil sizeof(lwpstatus)) != -1); 12341.149Skamil 12351.180Skamil DPRINTF("Assert that there exists a single thread only\n"); 12361.180Skamil ATF_REQUIRE_EQ(lwpstatus.pl_lwpid, 0); 12371.180Skamil } 12381.149Skamil 12391.180Skamil DPRINTF("Before resuming the child process where it left off and " 12401.180Skamil "without signal to be sent\n"); 12411.180Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, SIGKILL) != -1); 12421.149Skamil 12431.180Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12441.180Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 12451.149Skamil 12461.180Skamil validate_status_signaled(status, SIGKILL, 0); 12471.149Skamil 12481.180Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 12491.180Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 12501.180Skamil} 12511.149Skamil 12521.180Skamil#define TRACEME_LWPINFO(test, threads, iter) \ 12531.180SkamilATF_TC(test); \ 12541.180SkamilATF_TC_HEAD(test, tc) \ 12551.180Skamil{ \ 12561.180Skamil atf_tc_set_md_var(tc, "descr", \ 12571.180Skamil "Verify " iter " with the child with " #threads \ 12581.180Skamil " spawned extra threads"); \ 12591.180Skamil} \ 12601.180Skamil \ 12611.180SkamilATF_TC_BODY(test, tc) \ 12621.180Skamil{ \ 12631.180Skamil \ 12641.180Skamil traceme_lwpinfo(threads, iter); \ 12651.180Skamil} 12661.149Skamil 12671.180SkamilTRACEME_LWPINFO(traceme_lwpinfo0, 0, "LWPINFO") 12681.180SkamilTRACEME_LWPINFO(traceme_lwpinfo1, 1, "LWPINFO") 12691.180SkamilTRACEME_LWPINFO(traceme_lwpinfo2, 2, "LWPINFO") 12701.180SkamilTRACEME_LWPINFO(traceme_lwpinfo3, 3, "LWPINFO") 12711.149Skamil 12721.180SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus, 0, "LWPINFO+LWPSTATUS") 12731.180SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus, 1, "LWPINFO+LWPSTATUS") 12741.180SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus, 2, "LWPINFO+LWPSTATUS") 12751.180SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus, 3, "LWPINFO+LWPSTATUS") 12761.149Skamil 12771.180SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus_pl_sigmask, 0, 12781.180Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 12791.180SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus_pl_sigmask, 1, 12801.180Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 12811.180SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus_pl_sigmask, 2, 12821.180Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 12831.180SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus_pl_sigmask, 3, 12841.180Skamil "LWPINFO+LWPSTATUS+pl_sigmask") 12851.149Skamil 12861.180SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus_pl_name, 0, 12871.180Skamil "LWPINFO+LWPSTATUS+pl_name") 12881.180SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus_pl_name, 1, 12891.180Skamil "LWPINFO+LWPSTATUS+pl_name") 12901.180SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus_pl_name, 2, 12911.180Skamil "LWPINFO+LWPSTATUS+pl_name") 12921.180SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus_pl_name, 3, 12931.180Skamil "LWPINFO+LWPSTATUS+pl_name") 12941.149Skamil 12951.180SkamilTRACEME_LWPINFO(traceme_lwpinfo0_lwpstatus_pl_private, 0, 12961.180Skamil "LWPINFO+LWPSTATUS+pl_private") 12971.180SkamilTRACEME_LWPINFO(traceme_lwpinfo1_lwpstatus_pl_private, 1, 12981.180Skamil "LWPINFO+LWPSTATUS+pl_private") 12991.180SkamilTRACEME_LWPINFO(traceme_lwpinfo2_lwpstatus_pl_private, 2, 13001.180Skamil "LWPINFO+LWPSTATUS+pl_private") 13011.180SkamilTRACEME_LWPINFO(traceme_lwpinfo3_lwpstatus_pl_private, 3, 13021.180Skamil "LWPINFO+LWPSTATUS+pl_private") 13031.149Skamil 13041.180SkamilTRACEME_LWPINFO(traceme_lwpnext0, 0, "LWPNEXT") 13051.180SkamilTRACEME_LWPINFO(traceme_lwpnext1, 1, "LWPNEXT") 13061.180SkamilTRACEME_LWPINFO(traceme_lwpnext2, 2, "LWPNEXT") 13071.180SkamilTRACEME_LWPINFO(traceme_lwpnext3, 3, "LWPNEXT") 13081.149Skamil 13091.180SkamilTRACEME_LWPINFO(traceme_lwpnext0_pl_sigmask, 0, "LWPNEXT+pl_sigmask") 13101.180SkamilTRACEME_LWPINFO(traceme_lwpnext1_pl_sigmask, 1, "LWPNEXT+pl_sigmask") 13111.180SkamilTRACEME_LWPINFO(traceme_lwpnext2_pl_sigmask, 2, "LWPNEXT+pl_sigmask") 13121.180SkamilTRACEME_LWPINFO(traceme_lwpnext3_pl_sigmask, 3, "LWPNEXT+pl_sigmask") 13131.149Skamil 13141.180SkamilTRACEME_LWPINFO(traceme_lwpnext0_pl_name, 0, "LWPNEXT+pl_name") 13151.180SkamilTRACEME_LWPINFO(traceme_lwpnext1_pl_name, 1, "LWPNEXT+pl_name") 13161.180SkamilTRACEME_LWPINFO(traceme_lwpnext2_pl_name, 2, "LWPNEXT+pl_name") 13171.180SkamilTRACEME_LWPINFO(traceme_lwpnext3_pl_name, 3, "LWPNEXT+pl_name") 13181.149Skamil 13191.180SkamilTRACEME_LWPINFO(traceme_lwpnext0_pl_private, 0, "LWPNEXT+pl_private") 13201.180SkamilTRACEME_LWPINFO(traceme_lwpnext1_pl_private, 1, "LWPNEXT+pl_private") 13211.180SkamilTRACEME_LWPINFO(traceme_lwpnext2_pl_private, 2, "LWPNEXT+pl_private") 13221.180SkamilTRACEME_LWPINFO(traceme_lwpnext3_pl_private, 3, "LWPNEXT+pl_private") 13231.149Skamil 13241.180Skamil/// ---------------------------------------------------------------------------- 13251.149Skamil 13261.180Skamil#if defined(TWAIT_HAVE_PID) 13271.180Skamilstatic void 13281.180Skamilattach_lwpinfo(const int threads) 13291.180Skamil{ 13301.180Skamil const int sigval = SIGINT; 13311.180Skamil struct msg_fds parent_tracee, parent_tracer; 13321.180Skamil const int exitval_tracer = 10; 13331.180Skamil pid_t tracee, tracer, wpid; 13341.180Skamil uint8_t msg = 0xde; /* dummy message for IPC based on pipe(2) */ 13351.180Skamil#if defined(TWAIT_HAVE_STATUS) 13361.180Skamil int status; 13371.180Skamil#endif 13381.180Skamil struct ptrace_lwpinfo lwp = {0, 0}; 13391.180Skamil struct ptrace_siginfo info; 13401.149Skamil 13411.180Skamil /* Maximum number of supported threads in this test */ 13421.180Skamil pthread_t t[3]; 13431.180Skamil int n, rv; 13441.149Skamil 13451.180Skamil DPRINTF("Spawn tracee\n"); 13461.180Skamil SYSCALL_REQUIRE(msg_open(&parent_tracee) == 0); 13471.180Skamil SYSCALL_REQUIRE(msg_open(&parent_tracer) == 0); 13481.180Skamil tracee = atf_utils_fork(); 13491.180Skamil if (tracee == 0) { 13501.180Skamil /* Wait for message from the parent */ 13511.180Skamil CHILD_TO_PARENT("tracee ready", parent_tracee, msg); 13521.149Skamil 13531.180Skamil CHILD_FROM_PARENT("spawn threads", parent_tracee, msg); 13541.149Skamil 13551.180Skamil for (n = 0; n < threads; n++) { 13561.180Skamil rv = pthread_create(&t[n], NULL, infinite_thread, NULL); 13571.180Skamil FORKEE_ASSERT(rv == 0); 13581.149Skamil } 13591.149Skamil 13601.180Skamil CHILD_TO_PARENT("tracee exit", parent_tracee, msg); 13611.149Skamil 13621.180Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 13631.180Skamil FORKEE_ASSERT(raise(sigval) == 0); 13641.149Skamil 13651.180Skamil /* NOTREACHED */ 13661.180Skamil FORKEE_ASSERTX(0 && "Not reached"); 13671.150Skamil } 13681.180Skamil PARENT_FROM_CHILD("tracee ready", parent_tracee, msg); 13691.150Skamil 13701.150Skamil DPRINTF("Spawn debugger\n"); 13711.150Skamil tracer = atf_utils_fork(); 13721.150Skamil if (tracer == 0) { 13731.180Skamil /* No IPC to communicate with the child */ 13741.150Skamil DPRINTF("Before calling PT_ATTACH from tracee %d\n", getpid()); 13751.150Skamil FORKEE_ASSERT(ptrace(PT_ATTACH, tracee, NULL, 0) != -1); 13761.150Skamil 13771.150Skamil /* Wait for tracee and assert that it was stopped w/ SIGSTOP */ 13781.150Skamil FORKEE_REQUIRE_SUCCESS( 13791.150Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 13801.150Skamil 13811.150Skamil forkee_status_stopped(status, SIGSTOP); 13821.150Skamil 13831.180Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 13841.180Skamil "tracee"); 13851.180Skamil FORKEE_ASSERT( 13861.150Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 13871.150Skamil 13881.150Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 13891.150Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 13901.180Skamil "si_errno=%#x\n", 13911.180Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 13921.180Skamil info.psi_siginfo.si_errno); 13931.150Skamil 13941.150Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, SIGSTOP); 13951.150Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_USER); 13961.150Skamil 13971.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for child\n"); 13981.180Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 13991.180Skamil != -1); 14001.180Skamil 14011.180Skamil DPRINTF("Assert that there exists a thread\n"); 14021.180Skamil FORKEE_ASSERTX(lwp.pl_lwpid > 0); 14031.180Skamil 14041.180Skamil DPRINTF("Assert that lwp thread %d received event " 14051.180Skamil "PL_EVENT_SIGNAL\n", lwp.pl_lwpid); 14061.180Skamil FORKEE_ASSERT_EQ(lwp.pl_event, PL_EVENT_SIGNAL); 14071.180Skamil 14081.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 14091.180Skamil "tracee\n"); 14101.180Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 14111.180Skamil != -1); 14121.180Skamil 14131.180Skamil DPRINTF("Assert that there are no more lwp threads in " 14141.180Skamil "tracee\n"); 14151.180Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 14161.180Skamil 14171.150Skamil /* Resume tracee with PT_CONTINUE */ 14181.150Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, 0) != -1); 14191.150Skamil 14201.150Skamil /* Inform parent that tracer has attached to tracee */ 14211.150Skamil CHILD_TO_PARENT("tracer ready", parent_tracer, msg); 14221.150Skamil 14231.180Skamil /* Wait for parent */ 14241.180Skamil CHILD_FROM_PARENT("tracer wait", parent_tracer, msg); 14251.150Skamil 14261.180Skamil /* Wait for tracee and assert that it raised a signal */ 14271.150Skamil FORKEE_REQUIRE_SUCCESS( 14281.150Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 14291.150Skamil 14301.180Skamil forkee_status_stopped(status, SIGINT); 14311.150Skamil 14321.180Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 14331.180Skamil "child"); 14341.180Skamil FORKEE_ASSERT( 14351.150Skamil ptrace(PT_GET_SIGINFO, tracee, &info, sizeof(info)) != -1); 14361.150Skamil 14371.150Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 14381.150Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 14391.180Skamil "si_errno=%#x\n", 14401.180Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 14411.180Skamil info.psi_siginfo.si_errno); 14421.150Skamil 14431.150Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_signo, sigval); 14441.150Skamil FORKEE_ASSERT_EQ(info.psi_siginfo.si_code, SI_LWP); 14451.150Skamil 14461.180Skamil memset(&lwp, 0, sizeof(lwp)); 14471.150Skamil 14481.180Skamil for (n = 0; n <= threads; n++) { 14491.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 14501.180Skamil "child\n"); 14511.180Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, 14521.180Skamil sizeof(lwp)) != -1); 14531.180Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 14541.150Skamil 14551.180Skamil DPRINTF("Assert that the thread exists\n"); 14561.180Skamil FORKEE_ASSERT(lwp.pl_lwpid > 0); 14571.150Skamil 14581.180Skamil DPRINTF("Assert that lwp thread %d received expected " 14591.180Skamil "event\n", lwp.pl_lwpid); 14601.180Skamil FORKEE_ASSERT_EQ(lwp.pl_event, 14611.180Skamil info.psi_lwpid == lwp.pl_lwpid ? 14621.180Skamil PL_EVENT_SIGNAL : PL_EVENT_NONE); 14631.180Skamil } 14641.180Skamil DPRINTF("Before calling ptrace(2) with PT_LWPINFO for " 14651.180Skamil "tracee\n"); 14661.180Skamil FORKEE_ASSERT(ptrace(PT_LWPINFO, tracee, &lwp, sizeof(lwp)) 14671.180Skamil != -1); 14681.180Skamil DPRINTF("LWP=%d\n", lwp.pl_lwpid); 14691.150Skamil 14701.180Skamil DPRINTF("Assert that there are no more threads\n"); 14711.180Skamil FORKEE_ASSERT_EQ(lwp.pl_lwpid, 0); 14721.150Skamil 14731.180Skamil DPRINTF("Before resuming the child process where it left off " 14741.150Skamil "and without signal to be sent\n"); 14751.180Skamil FORKEE_ASSERT(ptrace(PT_CONTINUE, tracee, (void *)1, SIGKILL) 14761.180Skamil != -1); 14771.150Skamil 14781.180Skamil /* Wait for tracee and assert that it exited */ 14791.180Skamil FORKEE_REQUIRE_SUCCESS( 14801.180Skamil wpid = TWAIT_GENERIC(tracee, &status, 0), tracee); 14811.150Skamil 14821.180Skamil forkee_status_signaled(status, SIGKILL, 0); 14831.150Skamil 14841.150Skamil DPRINTF("Before exiting of the tracer process\n"); 14851.180Skamil _exit(exitval_tracer); 14861.97Skamil } 14871.97Skamil 14881.180Skamil DPRINTF("Wait for the tracer to attach to the tracee\n"); 14891.180Skamil PARENT_FROM_CHILD("tracer ready", parent_tracer, msg); 14901.97Skamil 14911.180Skamil DPRINTF("Resume the tracee and spawn threads\n"); 14921.180Skamil PARENT_TO_CHILD("spawn threads", parent_tracee, msg); 14931.97Skamil 14941.180Skamil DPRINTF("Resume the tracee and let it exit\n"); 14951.180Skamil PARENT_FROM_CHILD("tracee exit", parent_tracee, msg); 14961.97Skamil 14971.180Skamil DPRINTF("Resume the tracer and let it detect multiple threads\n"); 14981.180Skamil PARENT_TO_CHILD("tracer wait", parent_tracer, msg); 14991.1Skamil 15001.180Skamil DPRINTF("Wait for tracer to finish its job and exit - calling %s()\n", 15011.180Skamil TWAIT_FNAME); 15021.180Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracer, &status, 0), 15031.180Skamil tracer); 15041.1Skamil 15051.180Skamil validate_status_exited(status, exitval_tracer); 15061.1Skamil 15071.180Skamil DPRINTF("Wait for tracee to finish its job and exit - calling %s()\n", 15081.180Skamil TWAIT_FNAME); 15091.180Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(tracee, &status, WNOHANG), 15101.180Skamil tracee); 15111.1Skamil 15121.180Skamil validate_status_signaled(status, SIGKILL, 0); 15131.1Skamil 15141.180Skamil msg_close(&parent_tracer); 15151.180Skamil msg_close(&parent_tracee); 15161.1Skamil} 15171.1Skamil 15181.180Skamil#define ATTACH_LWPINFO(test, threads) \ 15191.97SkamilATF_TC(test); \ 15201.97SkamilATF_TC_HEAD(test, tc) \ 15211.97Skamil{ \ 15221.180Skamil atf_tc_set_md_var(tc, "descr", \ 15231.180Skamil "Verify LWPINFO with the child with " #threads \ 15241.180Skamil " spawned extra threads (tracer is not the original " \ 15251.180Skamil "parent)"); \ 15261.97Skamil} \ 15271.97Skamil \ 15281.97SkamilATF_TC_BODY(test, tc) \ 15291.97Skamil{ \ 15301.97Skamil \ 15311.180Skamil attach_lwpinfo(threads); \ 15321.97Skamil} 15331.97Skamil 15341.180SkamilATTACH_LWPINFO(attach_lwpinfo0, 0) 15351.180SkamilATTACH_LWPINFO(attach_lwpinfo1, 1) 15361.180SkamilATTACH_LWPINFO(attach_lwpinfo2, 2) 15371.180SkamilATTACH_LWPINFO(attach_lwpinfo3, 3) 15381.180Skamil#endif 15391.97Skamil 15401.82Skamil/// ---------------------------------------------------------------------------- 15411.82Skamil 15421.83Skamilstatic void 15431.180Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught) 15441.1Skamil{ 15451.180Skamil const int exitval = 5; 15461.180Skamil const int sigval = SIGINT; 15471.180Skamil const int sigfaked = SIGTRAP; 15481.180Skamil const int sicodefaked = TRAP_BRKPT; 15491.1Skamil pid_t child, wpid; 15501.180Skamil struct sigaction sa; 15511.1Skamil#if defined(TWAIT_HAVE_STATUS) 15521.1Skamil int status; 15531.1Skamil#endif 15541.83Skamil struct ptrace_siginfo info; 15551.180Skamil memset(&info, 0, sizeof(info)); 15561.83Skamil 15571.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 15581.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 15591.1Skamil if (child == 0) { 15601.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 15611.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 15621.1Skamil 15631.180Skamil sa.sa_sigaction = sah; 15641.180Skamil sa.sa_flags = SA_SIGINFO; 15651.180Skamil sigemptyset(&sa.sa_mask); 15661.180Skamil 15671.180Skamil FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL) 15681.180Skamil != -1); 15691.153Skamil 15701.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 15711.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 15721.1Skamil 15731.180Skamil FORKEE_ASSERT_EQ(*signal_caught, 1); 15741.1Skamil 15751.180Skamil DPRINTF("Before exiting of the child process\n"); 15761.180Skamil _exit(exitval); 15771.1Skamil } 15781.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 15791.1Skamil 15801.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 15811.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 15821.1Skamil 15831.1Skamil validate_status_stopped(status, sigval); 15841.1Skamil 15851.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 15861.83Skamil SYSCALL_REQUIRE( 15871.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 15881.1Skamil 15891.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 15901.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 15911.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 15921.83Skamil info.psi_siginfo.si_errno); 15931.1Skamil 15941.180Skamil if (faked) { 15951.180Skamil DPRINTF("Before setting new faked signal to signo=%d " 15961.180Skamil "si_code=%d\n", sigfaked, sicodefaked); 15971.180Skamil info.psi_siginfo.si_signo = sigfaked; 15981.180Skamil info.psi_siginfo.si_code = sicodefaked; 15991.83Skamil } 16001.1Skamil 16011.180Skamil DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n"); 16021.180Skamil SYSCALL_REQUIRE( 16031.180Skamil ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1); 16041.1Skamil 16051.180Skamil if (faked) { 16061.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 16071.83Skamil "child\n"); 16081.180Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 16091.180Skamil sizeof(info)) != -1); 16101.1Skamil 16111.180Skamil DPRINTF("Before checking siginfo_t\n"); 16121.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked); 16131.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked); 16141.83Skamil } 16151.1Skamil 16161.180Skamil DPRINTF("Before resuming the child process where it left off and " 16171.180Skamil "without signal to be sent\n"); 16181.180Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 16191.180Skamil faked ? sigfaked : sigval) != -1); 16201.1Skamil 16211.180Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16221.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 16231.1Skamil 16241.180Skamil validate_status_exited(status, exitval); 16251.1Skamil 16261.180Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 16271.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 16281.1Skamil} 16291.1Skamil 16301.180Skamil#define PTRACE_SIGINFO(test, faked) \ 16311.83SkamilATF_TC(test); \ 16321.83SkamilATF_TC_HEAD(test, tc) \ 16331.83Skamil{ \ 16341.180Skamil atf_tc_set_md_var(tc, "descr", \ 16351.180Skamil "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls" \ 16361.180Skamil "with%s setting signal to new value", faked ? "" : "out"); \ 16371.180Skamil} \ 16381.180Skamil \ 16391.180Skamilstatic int test##_caught = 0; \ 16401.180Skamil \ 16411.180Skamilstatic void \ 16421.180Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx) \ 16431.180Skamil{ \ 16441.180Skamil if (faked) { \ 16451.180Skamil FORKEE_ASSERT_EQ(sig, SIGTRAP); \ 16461.180Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP); \ 16471.180Skamil FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT); \ 16481.180Skamil } else { \ 16491.180Skamil FORKEE_ASSERT_EQ(sig, SIGINT); \ 16501.180Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGINT); \ 16511.180Skamil FORKEE_ASSERT_EQ(info->si_code, SI_LWP); \ 16521.180Skamil } \ 16531.180Skamil \ 16541.180Skamil ++ test##_caught; \ 16551.83Skamil} \ 16561.83Skamil \ 16571.83SkamilATF_TC_BODY(test, tc) \ 16581.83Skamil{ \ 16591.83Skamil \ 16601.180Skamil ptrace_siginfo(faked, test##_sighandler, & test##_caught); \ 16611.83Skamil} 16621.83Skamil 16631.180SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false) 16641.180SkamilPTRACE_SIGINFO(siginfo_set_faked, true) 16651.83Skamil 16661.83Skamil/// ---------------------------------------------------------------------------- 16671.83Skamil 16681.180Skamilstatic void 16691.180Skamiltraceme_exec(bool masked, bool ignored) 16701.1Skamil{ 16711.180Skamil const int sigval = SIGTRAP; 16721.1Skamil pid_t child, wpid; 16731.1Skamil#if defined(TWAIT_HAVE_STATUS) 16741.1Skamil int status; 16751.1Skamil#endif 16761.180Skamil struct sigaction sa; 16771.180Skamil struct ptrace_siginfo info; 16781.1Skamil sigset_t intmask; 16791.180Skamil struct kinfo_proc2 kp; 16801.180Skamil size_t len = sizeof(kp); 16811.180Skamil 16821.180Skamil int name[6]; 16831.180Skamil const size_t namelen = __arraycount(name); 16841.180Skamil ki_sigset_t kp_sigmask; 16851.180Skamil ki_sigset_t kp_sigignore; 16861.180Skamil 16871.180Skamil memset(&info, 0, sizeof(info)); 16881.1Skamil 16891.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 16901.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 16911.1Skamil if (child == 0) { 16921.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 16931.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 16941.1Skamil 16951.180Skamil if (masked) { 16961.180Skamil sigemptyset(&intmask); 16971.180Skamil sigaddset(&intmask, sigval); 16981.180Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 16991.180Skamil } 17001.1Skamil 17011.180Skamil if (ignored) { 17021.180Skamil memset(&sa, 0, sizeof(sa)); 17031.180Skamil sa.sa_handler = SIG_IGN; 17041.180Skamil sigemptyset(&sa.sa_mask); 17051.180Skamil FORKEE_ASSERT(sigaction(sigval, &sa, NULL) != -1); 17061.180Skamil } 17071.1Skamil 17081.180Skamil DPRINTF("Before calling execve(2) from child\n"); 17091.180Skamil execlp("/bin/echo", "/bin/echo", NULL); 17101.1Skamil 17111.180Skamil FORKEE_ASSERT(0 && "Not reached"); 17121.1Skamil } 17131.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 17141.1Skamil 17151.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17161.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17171.1Skamil 17181.1Skamil validate_status_stopped(status, sigval); 17191.1Skamil 17201.180Skamil name[0] = CTL_KERN, 17211.180Skamil name[1] = KERN_PROC2, 17221.180Skamil name[2] = KERN_PROC_PID; 17231.180Skamil name[3] = getpid(); 17241.180Skamil name[4] = sizeof(kp); 17251.180Skamil name[5] = 1; 17261.180Skamil 17271.180Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 17281.180Skamil 17291.180Skamil if (masked) 17301.180Skamil kp_sigmask = kp.p_sigmask; 17311.180Skamil 17321.180Skamil if (ignored) 17331.180Skamil kp_sigignore = kp.p_sigignore; 17341.180Skamil 17351.180Skamil name[3] = getpid(); 17361.180Skamil 17371.180Skamil ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0); 17381.180Skamil 17391.180Skamil if (masked) { 17401.180Skamil DPRINTF("kp_sigmask=" 17411.180Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 17421.180Skamil kp_sigmask.__bits[0], kp_sigmask.__bits[1], 17431.180Skamil kp_sigmask.__bits[2], kp_sigmask.__bits[3]); 17441.180Skamil 17451.180Skamil DPRINTF("kp.p_sigmask=" 17461.180Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 17471.180Skamil kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1], 17481.180Skamil kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]); 17491.180Skamil 17501.180Skamil ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask, 17511.180Skamil sizeof(kp_sigmask))); 17521.180Skamil } 17531.180Skamil 17541.180Skamil if (ignored) { 17551.180Skamil DPRINTF("kp_sigignore=" 17561.180Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 17571.180Skamil kp_sigignore.__bits[0], kp_sigignore.__bits[1], 17581.180Skamil kp_sigignore.__bits[2], kp_sigignore.__bits[3]); 17591.180Skamil 17601.180Skamil DPRINTF("kp.p_sigignore=" 17611.180Skamil "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02" PRIx32"\n", 17621.180Skamil kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1], 17631.180Skamil kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]); 17641.180Skamil 17651.180Skamil ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore, 17661.180Skamil sizeof(kp_sigignore))); 17671.180Skamil } 17681.180Skamil 17691.180Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 17701.180Skamil SYSCALL_REQUIRE( 17711.180Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 17721.1Skamil 17731.180Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 17741.180Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 17751.180Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 17761.180Skamil info.psi_siginfo.si_errno); 17771.1Skamil 17781.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 17791.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 17801.1Skamil 17811.13Schristos DPRINTF("Before resuming the child process where it left off and " 17821.1Skamil "without signal to be sent\n"); 17831.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 17841.1Skamil 17851.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17861.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 17871.1Skamil 17881.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 17891.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 17901.1Skamil} 17911.1Skamil 17921.180Skamil#define TRACEME_EXEC(test, masked, ignored) \ 17931.180SkamilATF_TC(test); \ 17941.180SkamilATF_TC_HEAD(test, tc) \ 17951.180Skamil{ \ 17961.180Skamil atf_tc_set_md_var(tc, "descr", \ 17971.180Skamil "Detect SIGTRAP TRAP_EXEC from " \ 17981.180Skamil "child%s%s", masked ? " with masked signal" : "", \ 17991.180Skamil masked ? " with ignored signal" : ""); \ 18001.180Skamil} \ 18011.180Skamil \ 18021.180SkamilATF_TC_BODY(test, tc) \ 18031.180Skamil{ \ 18041.180Skamil \ 18051.180Skamil traceme_exec(masked, ignored); \ 18061.180Skamil} 18071.180Skamil 18081.180SkamilTRACEME_EXEC(traceme_exec, false, false) 18091.180SkamilTRACEME_EXEC(traceme_signalmasked_exec, true, false) 18101.180SkamilTRACEME_EXEC(traceme_signalignored_exec, false, true) 18111.180Skamil 18121.84Skamil/// ---------------------------------------------------------------------------- 18131.84Skamil 18141.180Skamil#define TRACE_THREADS_NUM 100 18151.180Skamil 18161.180Skamilstatic volatile int done; 18171.180Skamilpthread_mutex_t trace_threads_mtx = PTHREAD_MUTEX_INITIALIZER; 18181.180Skamil 18191.180Skamilstatic void * 18201.180Skamiltrace_threads_cb(void *arg __unused) 18211.180Skamil{ 18221.180Skamil 18231.180Skamil pthread_mutex_lock(&trace_threads_mtx); 18241.180Skamil done++; 18251.180Skamil pthread_mutex_unlock(&trace_threads_mtx); 18261.180Skamil 18271.180Skamil while (done < TRACE_THREADS_NUM) 18281.180Skamil sched_yield(); 18291.180Skamil 18301.180Skamil return NULL; 18311.180Skamil} 18321.180Skamil 18331.99Skamilstatic void 18341.180Skamiltrace_threads(bool trace_create, bool trace_exit, bool masked) 18351.1Skamil{ 18361.1Skamil const int sigval = SIGSTOP; 18371.180Skamil pid_t child, wpid; 18381.1Skamil#if defined(TWAIT_HAVE_STATUS) 18391.1Skamil int status; 18401.1Skamil#endif 18411.1Skamil ptrace_state_t state; 18421.1Skamil const int slen = sizeof(state); 18431.1Skamil ptrace_event_t event; 18441.1Skamil const int elen = sizeof(event); 18451.99Skamil struct ptrace_siginfo info; 18461.180Skamil 18471.99Skamil sigset_t intmask; 18481.99Skamil 18491.180Skamil pthread_t t[TRACE_THREADS_NUM]; 18501.180Skamil int rv; 18511.180Skamil size_t n; 18521.180Skamil lwpid_t lid; 18531.1Skamil 18541.180Skamil /* Track created and exited threads */ 18551.180Skamil struct lwp_event_count traced_lwps[__arraycount(t)] = {{0, 0}}; 18561.14Schristos 18571.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 18581.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 18591.1Skamil if (child == 0) { 18601.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 18611.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 18621.1Skamil 18631.99Skamil if (masked) { 18641.99Skamil sigemptyset(&intmask); 18651.99Skamil sigaddset(&intmask, SIGTRAP); 18661.99Skamil sigprocmask(SIG_BLOCK, &intmask, NULL); 18671.99Skamil } 18681.99Skamil 18691.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 18701.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 18711.1Skamil 18721.180Skamil for (n = 0; n < __arraycount(t); n++) { 18731.180Skamil rv = pthread_create(&t[n], NULL, trace_threads_cb, 18741.180Skamil NULL); 18751.180Skamil FORKEE_ASSERT(rv == 0); 18761.126Skamil } 18771.1Skamil 18781.180Skamil for (n = 0; n < __arraycount(t); n++) { 18791.180Skamil rv = pthread_join(t[n], NULL); 18801.180Skamil FORKEE_ASSERT(rv == 0); 18811.180Skamil } 18821.1Skamil 18831.180Skamil /* 18841.180Skamil * There is race between _exit() and pthread_join() detaching 18851.180Skamil * a thread. For simplicity kill the process after detecting 18861.180Skamil * LWP events. 18871.180Skamil */ 18881.180Skamil while (true) 18891.180Skamil continue; 18901.1Skamil 18911.180Skamil FORKEE_ASSERT(0 && "Not reached"); 18921.1Skamil } 18931.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 18941.1Skamil 18951.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 18961.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 18971.1Skamil 18981.1Skamil validate_status_stopped(status, sigval); 18991.1Skamil 19001.99Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 19011.99Skamil SYSCALL_REQUIRE( 19021.99Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 19031.99Skamil 19041.180Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 19051.180Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 19061.180Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 19071.180Skamil info.psi_siginfo.si_errno); 19081.180Skamil 19091.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 19101.99Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 19111.1Skamil 19121.180Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 19131.180Skamil memset(&event, 0, sizeof(event)); 19141.180Skamil if (trace_create) 19151.180Skamil event.pe_set_event |= PTRACE_LWP_CREATE; 19161.180Skamil if (trace_exit) 19171.180Skamil event.pe_set_event |= PTRACE_LWP_EXIT; 19181.99Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 19191.1Skamil 19201.99Skamil DPRINTF("Before resuming the child process where it left off and " 19211.99Skamil "without signal to be sent\n"); 19221.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 19231.1Skamil 19241.180Skamil for (n = 0; n < (trace_create ? __arraycount(t) : 0); n++) { 19251.180Skamil DPRINTF("Before calling %s() for the child - expected stopped " 19261.180Skamil "SIGTRAP\n", TWAIT_FNAME); 19271.99Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 19281.99Skamil child); 19291.1Skamil 19301.99Skamil validate_status_stopped(status, SIGTRAP); 19311.1Skamil 19321.180Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 19331.180Skamil "child\n"); 19341.180Skamil SYSCALL_REQUIRE( 19351.180Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 19361.180Skamil 19371.180Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 19381.180Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 19391.180Skamil "si_errno=%#x\n", 19401.180Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 19411.180Skamil info.psi_siginfo.si_errno); 19421.1Skamil 19431.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 19441.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 19451.1Skamil 19461.180Skamil SYSCALL_REQUIRE( 19471.180Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 19481.1Skamil 19491.180Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 19501.180Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 19511.1Skamil 19521.180Skamil lid = state.pe_lwp; 19531.180Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 19541.1Skamil 19551.180Skamil *FIND_EVENT_COUNT(traced_lwps, lid) += 1; 19561.1Skamil 19571.180Skamil DPRINTF("Before resuming the child process where it left off " 19581.180Skamil "and without signal to be sent\n"); 19591.180Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 19601.180Skamil } 19611.1Skamil 19621.180Skamil for (n = 0; n < (trace_exit ? __arraycount(t) : 0); n++) { 19631.180Skamil DPRINTF("Before calling %s() for the child - expected stopped " 19641.180Skamil "SIGTRAP\n", TWAIT_FNAME); 19651.180Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 19661.180Skamil child); 19671.1Skamil 19681.99Skamil validate_status_stopped(status, SIGTRAP); 19691.1Skamil 19701.180Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 19711.180Skamil "child\n"); 19721.180Skamil SYSCALL_REQUIRE( 19731.180Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 19741.1Skamil 19751.180Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 19761.180Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 19771.180Skamil "si_errno=%#x\n", 19781.180Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 19791.180Skamil info.psi_siginfo.si_errno); 19801.1Skamil 19811.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 19821.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 19831.14Schristos 19841.180Skamil SYSCALL_REQUIRE( 19851.180Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 19861.1Skamil 19871.180Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 19881.180Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 19891.1Skamil 19901.180Skamil lid = state.pe_lwp; 19911.180Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 19921.1Skamil 19931.180Skamil if (trace_create) { 19941.180Skamil int *count = FIND_EVENT_COUNT(traced_lwps, lid); 19951.180Skamil ATF_REQUIRE_EQ(*count, 1); 19961.180Skamil *count = 0; 19971.99Skamil } 19981.1Skamil 19991.99Skamil DPRINTF("Before resuming the child process where it left off " 20001.99Skamil "and without signal to be sent\n"); 20011.99Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 20021.1Skamil } 20031.1Skamil 20041.180Skamil kill(child, SIGKILL); 20051.180Skamil 20061.180Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 20071.180Skamil TWAIT_FNAME); 20081.180Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 20091.180Skamil 20101.180Skamil validate_status_signaled(status, SIGKILL, 0); 20111.1Skamil 20121.180Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 20131.180Skamil TWAIT_FNAME); 20141.180Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 20151.180Skamil} 20161.1Skamil 20171.180Skamil#define TRACE_THREADS(test, trace_create, trace_exit, mask) \ 20181.180SkamilATF_TC(test); \ 20191.180SkamilATF_TC_HEAD(test, tc) \ 20201.180Skamil{ \ 20211.180Skamil atf_tc_set_md_var(tc, "descr", \ 20221.180Skamil "Verify spawning threads with%s tracing LWP create and" \ 20231.180Skamil "with%s tracing LWP exit", trace_create ? "" : "out", \ 20241.180Skamil trace_exit ? "" : "out"); \ 20251.180Skamil} \ 20261.180Skamil \ 20271.180SkamilATF_TC_BODY(test, tc) \ 20281.180Skamil{ \ 20291.180Skamil \ 20301.180Skamil trace_threads(trace_create, trace_exit, mask); \ 20311.180Skamil} 20321.1Skamil 20331.180SkamilTRACE_THREADS(trace_thread_nolwpevents, false, false, false) 20341.180SkamilTRACE_THREADS(trace_thread_lwpexit, false, true, false) 20351.180SkamilTRACE_THREADS(trace_thread_lwpcreate, true, false, false) 20361.180SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit, true, true, false) 20371.102Skamil 20381.180SkamilTRACE_THREADS(trace_thread_lwpexit_masked_sigtrap, false, true, true) 20391.180SkamilTRACE_THREADS(trace_thread_lwpcreate_masked_sigtrap, true, false, true) 20401.180SkamilTRACE_THREADS(trace_thread_lwpcreate_and_exit_masked_sigtrap, true, true, true) 20411.1Skamil 20421.180Skamil/// ---------------------------------------------------------------------------- 20431.1Skamil 20441.151Skamilstatic void * 20451.151Skamilthread_and_exec_thread_cb(void *arg __unused) 20461.151Skamil{ 20471.151Skamil 20481.151Skamil execlp("/bin/echo", "/bin/echo", NULL); 20491.151Skamil 20501.151Skamil abort(); 20511.151Skamil} 20521.151Skamil 20531.151Skamilstatic void 20541.151Skamilthreads_and_exec(void) 20551.151Skamil{ 20561.151Skamil const int sigval = SIGSTOP; 20571.151Skamil pid_t child, wpid; 20581.151Skamil#if defined(TWAIT_HAVE_STATUS) 20591.151Skamil int status; 20601.151Skamil#endif 20611.151Skamil ptrace_state_t state; 20621.151Skamil const int slen = sizeof(state); 20631.151Skamil ptrace_event_t event; 20641.151Skamil const int elen = sizeof(event); 20651.151Skamil struct ptrace_siginfo info; 20661.151Skamil 20671.151Skamil pthread_t t; 20681.151Skamil lwpid_t lid; 20691.151Skamil 20701.151Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 20711.151Skamil SYSCALL_REQUIRE((child = fork()) != -1); 20721.151Skamil if (child == 0) { 20731.151Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 20741.151Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 20751.151Skamil 20761.151Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 20771.151Skamil FORKEE_ASSERT(raise(sigval) == 0); 20781.151Skamil 20791.151Skamil FORKEE_ASSERT(pthread_create(&t, NULL, 20801.151Skamil thread_and_exec_thread_cb, NULL) == 0); 20811.151Skamil 20821.151Skamil for (;;) 20831.151Skamil continue; 20841.151Skamil 20851.151Skamil FORKEE_ASSERT(0 && "Not reached"); 20861.151Skamil } 20871.151Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 20881.151Skamil 20891.151Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 20901.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 20911.151Skamil 20921.151Skamil validate_status_stopped(status, sigval); 20931.151Skamil 20941.151Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 20951.151Skamil SYSCALL_REQUIRE( 20961.151Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 20971.151Skamil 20981.151Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 20991.151Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 21001.151Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 21011.151Skamil info.psi_siginfo.si_errno); 21021.151Skamil 21031.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 21041.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 21051.151Skamil 21061.151Skamil DPRINTF("Set LWP event mask for the child %d\n", child); 21071.151Skamil memset(&event, 0, sizeof(event)); 21081.151Skamil event.pe_set_event |= PTRACE_LWP_CREATE | PTRACE_LWP_EXIT; 21091.151Skamil SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 21101.151Skamil 21111.151Skamil DPRINTF("Before resuming the child process where it left off and " 21121.151Skamil "without signal to be sent\n"); 21131.151Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 21141.151Skamil 21151.151Skamil DPRINTF("Before calling %s() for the child - expected stopped " 21161.151Skamil "SIGTRAP\n", TWAIT_FNAME); 21171.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 21181.151Skamil child); 21191.151Skamil 21201.151Skamil validate_status_stopped(status, SIGTRAP); 21211.151Skamil 21221.151Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 21231.151Skamil "child\n"); 21241.151Skamil SYSCALL_REQUIRE( 21251.151Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 21261.151Skamil 21271.151Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21281.151Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21291.151Skamil "si_errno=%#x\n", 21301.151Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 21311.151Skamil info.psi_siginfo.si_errno); 21321.151Skamil 21331.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 21341.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 21351.151Skamil 21361.151Skamil SYSCALL_REQUIRE( 21371.151Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 21381.151Skamil 21391.151Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_CREATE, 21401.151Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_CREATE); 21411.151Skamil 21421.151Skamil lid = state.pe_lwp; 21431.151Skamil DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 21441.151Skamil 21451.151Skamil DPRINTF("Before resuming the child process where it left off " 21461.151Skamil "and without signal to be sent\n"); 21471.151Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 21481.151Skamil 21491.151Skamil DPRINTF("Before calling %s() for the child - expected stopped " 21501.151Skamil "SIGTRAP\n", TWAIT_FNAME); 21511.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 21521.151Skamil child); 21531.151Skamil 21541.151Skamil validate_status_stopped(status, SIGTRAP); 21551.151Skamil 21561.151Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 21571.151Skamil "child\n"); 21581.151Skamil SYSCALL_REQUIRE( 21591.151Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 21601.151Skamil 21611.151Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21621.151Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21631.151Skamil "si_errno=%#x\n", 21641.151Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 21651.151Skamil info.psi_siginfo.si_errno); 21661.151Skamil 21671.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 21681.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_LWP); 21691.151Skamil 21701.151Skamil SYSCALL_REQUIRE( 21711.151Skamil ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 21721.151Skamil 21731.151Skamil ATF_REQUIRE_EQ_MSG(state.pe_report_event, PTRACE_LWP_EXIT, 21741.151Skamil "%d != %d", state.pe_report_event, PTRACE_LWP_EXIT); 21751.151Skamil 21761.151Skamil lid = state.pe_lwp; 21771.151Skamil DPRINTF("Reported PTRACE_LWP_EXIT event with lid %d\n", lid); 21781.151Skamil 21791.151Skamil DPRINTF("Before resuming the child process where it left off " 21801.151Skamil "and without signal to be sent\n"); 21811.151Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 21821.151Skamil 21831.151Skamil DPRINTF("Before calling %s() for the child - expected stopped " 21841.151Skamil "SIGTRAP\n", TWAIT_FNAME); 21851.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 21861.151Skamil child); 21871.151Skamil 21881.151Skamil validate_status_stopped(status, SIGTRAP); 21891.151Skamil 21901.151Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 21911.151Skamil "child\n"); 21921.151Skamil SYSCALL_REQUIRE( 21931.151Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 21941.151Skamil 21951.151Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 21961.151Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 21971.151Skamil "si_errno=%#x\n", 21981.151Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 21991.151Skamil info.psi_siginfo.si_errno); 22001.151Skamil 22011.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 22021.151Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 22031.151Skamil 22041.151Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 22051.151Skamil 22061.151Skamil DPRINTF("Before calling %s() for the child - expected exited\n", 22071.151Skamil TWAIT_FNAME); 22081.151Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 22091.151Skamil 22101.151Skamil validate_status_signaled(status, SIGKILL, 0); 22111.151Skamil 22121.151Skamil DPRINTF("Before calling %s() for the child - expected no process\n", 22131.151Skamil TWAIT_FNAME); 22141.151Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 22151.151Skamil} 22161.151Skamil 22171.151SkamilATF_TC(threads_and_exec); 22181.151SkamilATF_TC_HEAD(threads_and_exec, tc) 22191.151Skamil{ 22201.151Skamil atf_tc_set_md_var(tc, "descr", 22211.151Skamil "Verify that multithreaded application on exec() will report " 22221.151Skamil "LWP_EXIT events"); 22231.151Skamil} 22241.151Skamil 22251.151SkamilATF_TC_BODY(threads_and_exec, tc) 22261.151Skamil{ 22271.151Skamil 22281.151Skamil threads_and_exec(); 22291.151Skamil} 22301.151Skamil 22311.151Skamil/// ---------------------------------------------------------------------------- 22321.151Skamil 22331.154SkamilATF_TC(suspend_no_deadlock); 22341.154SkamilATF_TC_HEAD(suspend_no_deadlock, tc) 22351.1Skamil{ 22361.1Skamil atf_tc_set_md_var(tc, "descr", 22371.1Skamil "Verify that the while the only thread within a process is " 22381.1Skamil "suspended, the whole process cannot be unstopped"); 22391.1Skamil} 22401.1Skamil 22411.154SkamilATF_TC_BODY(suspend_no_deadlock, tc) 22421.1Skamil{ 22431.1Skamil const int exitval = 5; 22441.1Skamil const int sigval = SIGSTOP; 22451.1Skamil pid_t child, wpid; 22461.1Skamil#if defined(TWAIT_HAVE_STATUS) 22471.1Skamil int status; 22481.1Skamil#endif 22491.1Skamil struct ptrace_siginfo psi; 22501.1Skamil 22511.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 22521.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 22531.1Skamil if (child == 0) { 22541.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 22551.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 22561.1Skamil 22571.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 22581.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 22591.1Skamil 22601.13Schristos DPRINTF("Before exiting of the child process\n"); 22611.1Skamil _exit(exitval); 22621.1Skamil } 22631.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 22641.1Skamil 22651.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 22661.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 22671.1Skamil 22681.1Skamil validate_status_stopped(status, sigval); 22691.1Skamil 22701.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 22711.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 22721.1Skamil 22731.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 22741.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 22751.1Skamil 22761.13Schristos DPRINTF("Before resuming the child process where it left off and " 22771.1Skamil "without signal to be sent\n"); 22781.1Skamil ATF_REQUIRE_ERRNO(EDEADLK, 22791.1Skamil ptrace(PT_CONTINUE, child, (void *)1, 0) == -1); 22801.1Skamil 22811.13Schristos DPRINTF("Before resuming LWP %d\n", psi.psi_lwpid); 22821.13Schristos SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, psi.psi_lwpid) != -1); 22831.1Skamil 22841.13Schristos DPRINTF("Before resuming the child process where it left off and " 22851.1Skamil "without signal to be sent\n"); 22861.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 22871.1Skamil 22881.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 22891.1Skamil TWAIT_FNAME); 22901.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 22911.1Skamil 22921.1Skamil validate_status_exited(status, exitval); 22931.1Skamil 22941.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 22951.1Skamil TWAIT_FNAME); 22961.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 22971.1Skamil} 22981.1Skamil 22991.154Skamil/// ---------------------------------------------------------------------------- 23001.154Skamil 23011.155Skamilstatic pthread_barrier_t barrier1_resume; 23021.155Skamilstatic pthread_barrier_t barrier2_resume; 23031.154Skamil 23041.155Skamilstatic void * 23051.155Skamilresume_thread(void *arg) 23061.154Skamil{ 23071.154Skamil 23081.155Skamil raise(SIGUSR1); 23091.155Skamil 23101.155Skamil pthread_barrier_wait(&barrier1_resume); 23111.155Skamil 23121.155Skamil /* Debugger will suspend the process here */ 23131.155Skamil 23141.155Skamil pthread_barrier_wait(&barrier2_resume); 23151.154Skamil 23161.155Skamil raise(SIGUSR2); 23171.155Skamil 23181.155Skamil return infinite_thread(arg); 23191.154Skamil} 23201.154Skamil 23211.155SkamilATF_TC(resume); 23221.155SkamilATF_TC_HEAD(resume, tc) 23231.1Skamil{ 23241.1Skamil atf_tc_set_md_var(tc, "descr", 23251.1Skamil "Verify that a thread can be suspended by a debugger and later " 23261.1Skamil "resumed by the debugger"); 23271.1Skamil} 23281.1Skamil 23291.155SkamilATF_TC_BODY(resume, tc) 23301.1Skamil{ 23311.1Skamil const int sigval = SIGSTOP; 23321.1Skamil pid_t child, wpid; 23331.1Skamil#if defined(TWAIT_HAVE_STATUS) 23341.1Skamil int status; 23351.1Skamil#endif 23361.1Skamil lwpid_t lid; 23371.1Skamil struct ptrace_siginfo psi; 23381.155Skamil pthread_t t; 23391.1Skamil 23401.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 23411.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 23421.1Skamil if (child == 0) { 23431.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 23441.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 23451.1Skamil 23461.155Skamil pthread_barrier_init(&barrier1_resume, NULL, 2); 23471.155Skamil pthread_barrier_init(&barrier2_resume, NULL, 2); 23481.155Skamil 23491.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 23501.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 23511.1Skamil 23521.155Skamil DPRINTF("Before creating new thread in child\n"); 23531.155Skamil FORKEE_ASSERT(pthread_create(&t, NULL, resume_thread, NULL) == 0); 23541.1Skamil 23551.155Skamil pthread_barrier_wait(&barrier1_resume); 23561.1Skamil 23571.155Skamil pthread_barrier_wait(&barrier2_resume); 23581.1Skamil 23591.155Skamil infinite_thread(NULL); 23601.1Skamil } 23611.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 23621.1Skamil 23631.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 23641.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 23651.1Skamil 23661.1Skamil validate_status_stopped(status, sigval); 23671.1Skamil 23681.13Schristos DPRINTF("Before resuming the child process where it left off and " 23691.1Skamil "without signal to be sent\n"); 23701.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 23711.1Skamil 23721.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 23731.155Skamil "SIGUSR1\n", TWAIT_FNAME); 23741.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 23751.1Skamil 23761.155Skamil validate_status_stopped(status, SIGUSR1); 23771.1Skamil 23781.13Schristos DPRINTF("Before reading siginfo and lwpid_t\n"); 23791.13Schristos SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &psi, sizeof(psi)) != -1); 23801.1Skamil 23811.13Schristos DPRINTF("Before suspending LWP %d\n", psi.psi_lwpid); 23821.13Schristos SYSCALL_REQUIRE(ptrace(PT_SUSPEND, child, NULL, psi.psi_lwpid) != -1); 23831.1Skamil 23841.155Skamil lid = psi.psi_lwpid; 23851.1Skamil 23861.13Schristos DPRINTF("Before resuming the child process where it left off and " 23871.1Skamil "without signal to be sent\n"); 23881.13Schristos SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 23891.1Skamil 23901.155Skamil DPRINTF("Before suspending the parent for 1 second, we expect no signals\n"); 23911.155Skamil SYSCALL_REQUIRE(sleep(1) == 0); 23921.155Skamil 23931.155Skamil#if defined(TWAIT_HAVE_OPTIONS) 23941.155Skamil DPRINTF("Before calling %s() for the child - expected no status\n", 23951.155Skamil TWAIT_FNAME); 23961.155Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, WNOHANG), 0); 23971.155Skamil#endif 23981.155Skamil 23991.155Skamil DPRINTF("Before resuming the child process where it left off and " 24001.155Skamil "without signal to be sent\n"); 24011.155Skamil SYSCALL_REQUIRE(ptrace(PT_STOP, child, NULL, 0) != -1); 24021.155Skamil 24031.13Schristos DPRINTF("Before calling %s() for the child - expected stopped " 24041.155Skamil "SIGSTOP\n", TWAIT_FNAME); 24051.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 24061.1Skamil 24071.155Skamil validate_status_stopped(status, SIGSTOP); 24081.1Skamil 24091.155Skamil DPRINTF("Before resuming LWP %d\n", lid); 24101.155Skamil SYSCALL_REQUIRE(ptrace(PT_RESUME, child, NULL, lid) != -1); 24111.155Skamil 24121.155Skamil DPRINTF("Before resuming the child process where it left off and " 24131.155Skamil "without signal to be sent\n"); 24141.155Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 24151.1Skamil 24161.155Skamil DPRINTF("Before calling %s() for the child - expected stopped " 24171.155Skamil "SIGUSR2\n", TWAIT_FNAME); 24181.155Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 24191.1Skamil 24201.155Skamil validate_status_stopped(status, SIGUSR2); 24211.1Skamil 24221.13Schristos DPRINTF("Before resuming the child process where it left off and " 24231.1Skamil "without signal to be sent\n"); 24241.155Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1); 24251.1Skamil 24261.13Schristos DPRINTF("Before calling %s() for the child - expected exited\n", 24271.1Skamil TWAIT_FNAME); 24281.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 24291.1Skamil 24301.155Skamil validate_status_signaled(status, SIGKILL, 0); 24311.1Skamil 24321.13Schristos DPRINTF("Before calling %s() for the child - expected no process\n", 24331.1Skamil TWAIT_FNAME); 24341.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 24351.155Skamil} 24361.1Skamil 24371.155Skamil/// ---------------------------------------------------------------------------- 24381.1Skamil 24391.106Skamilstatic void 24401.122Skamiluser_va0_disable(int operation) 24411.122Skamil{ 24421.122Skamil pid_t child, wpid; 24431.122Skamil#if defined(TWAIT_HAVE_STATUS) 24441.122Skamil int status; 24451.122Skamil#endif 24461.122Skamil const int sigval = SIGSTOP; 24471.122Skamil int rv; 24481.122Skamil 24491.122Skamil struct ptrace_siginfo info; 24501.122Skamil 24511.122Skamil if (get_user_va0_disable() == 0) 24521.122Skamil atf_tc_skip("vm.user_va0_disable is set to 0"); 24531.122Skamil 24541.122Skamil memset(&info, 0, sizeof(info)); 24551.122Skamil 24561.122Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 24571.122Skamil SYSCALL_REQUIRE((child = fork()) != -1); 24581.122Skamil if (child == 0) { 24591.122Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 24601.122Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 24611.122Skamil 24621.122Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 24631.122Skamil FORKEE_ASSERT(raise(sigval) == 0); 24641.122Skamil 24651.122Skamil /* NOTREACHED */ 24661.122Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 24671.122Skamil __unreachable(); 24681.122Skamil } 24691.122Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 24701.122Skamil 24711.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 24721.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 24731.122Skamil 24741.122Skamil validate_status_stopped(status, sigval); 24751.122Skamil 24761.122Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 24771.122Skamil "child\n"); 24781.122Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 24791.122Skamil sizeof(info)) != -1); 24801.122Skamil 24811.122Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 24821.122Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 24831.122Skamil "si_errno=%#x\n", 24841.122Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 24851.122Skamil info.psi_siginfo.si_errno); 24861.122Skamil 24871.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 24881.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 24891.122Skamil 24901.122Skamil DPRINTF("Before resuming the child process in PC=0x0 " 24911.122Skamil "and without signal to be sent\n"); 24921.122Skamil errno = 0; 24931.122Skamil rv = ptrace(operation, child, (void *)0, 0); 24941.122Skamil ATF_REQUIRE_EQ(errno, EINVAL); 24951.122Skamil ATF_REQUIRE_EQ(rv, -1); 24961.122Skamil 24971.122Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 24981.122Skamil 24991.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 25001.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 25011.122Skamil validate_status_signaled(status, SIGKILL, 0); 25021.122Skamil 25031.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 25041.122Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 25051.122Skamil} 25061.122Skamil 25071.122Skamil#define USER_VA0_DISABLE(test, operation) \ 25081.122SkamilATF_TC(test); \ 25091.122SkamilATF_TC_HEAD(test, tc) \ 25101.122Skamil{ \ 25111.122Skamil atf_tc_set_md_var(tc, "descr", \ 25121.122Skamil "Verify behavior of " #operation " with PC set to 0x0"); \ 25131.122Skamil} \ 25141.122Skamil \ 25151.122SkamilATF_TC_BODY(test, tc) \ 25161.122Skamil{ \ 25171.122Skamil \ 25181.122Skamil user_va0_disable(operation); \ 25191.122Skamil} 25201.122Skamil 25211.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE) 25221.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL) 25231.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH) 25241.122Skamil 25251.122Skamil/// ---------------------------------------------------------------------------- 25261.122Skamil 25271.130Smgorny/* 25281.130Smgorny * Parse the core file and find the requested note. If the reading or parsing 25291.130Smgorny * fails, the test is failed. If the note is found, it is read onto buf, up to 25301.130Smgorny * buf_len. The actual length of the note is returned (which can be greater 25311.130Smgorny * than buf_len, indicating that it has been truncated). If the note is not 25321.130Smgorny * found, -1 is returned. 25331.172Sthorpej * 25341.172Sthorpej * If the note_name ends in '*', then we find the first note that matches 25351.172Sthorpej * the note_name prefix up to the '*' character, e.g.: 25361.172Sthorpej * 25371.172Sthorpej * NetBSD-CORE@* 25381.172Sthorpej * 25391.172Sthorpej * finds the first note whose name prefix matches "NetBSD-CORE@". 25401.130Smgorny */ 25411.130Smgornystatic ssize_t core_find_note(const char *core_path, 25421.130Smgorny const char *note_name, uint64_t note_type, void *buf, size_t buf_len) 25431.130Smgorny{ 25441.130Smgorny int core_fd; 25451.130Smgorny Elf *core_elf; 25461.130Smgorny size_t core_numhdr, i; 25471.130Smgorny ssize_t ret = -1; 25481.172Sthorpej size_t name_len = strlen(note_name); 25491.172Sthorpej bool prefix_match = false; 25501.172Sthorpej 25511.172Sthorpej if (note_name[name_len - 1] == '*') { 25521.172Sthorpej prefix_match = true; 25531.172Sthorpej name_len--; 25541.172Sthorpej } else { 25551.172Sthorpej /* note: we assume note name will be null-terminated */ 25561.172Sthorpej name_len++; 25571.172Sthorpej } 25581.130Smgorny 25591.130Smgorny SYSCALL_REQUIRE((core_fd = open(core_path, O_RDONLY)) != -1); 25601.130Smgorny SYSCALL_REQUIRE(elf_version(EV_CURRENT) != EV_NONE); 25611.130Smgorny SYSCALL_REQUIRE((core_elf = elf_begin(core_fd, ELF_C_READ, NULL))); 25621.130Smgorny 25631.130Smgorny SYSCALL_REQUIRE(elf_getphnum(core_elf, &core_numhdr) != 0); 25641.130Smgorny for (i = 0; i < core_numhdr && ret == -1; i++) { 25651.130Smgorny GElf_Phdr core_hdr; 25661.130Smgorny size_t offset; 25671.130Smgorny SYSCALL_REQUIRE(gelf_getphdr(core_elf, i, &core_hdr)); 25681.130Smgorny if (core_hdr.p_type != PT_NOTE) 25691.130Smgorny continue; 25701.130Smgorny 25711.130Smgorny for (offset = core_hdr.p_offset; 25721.130Smgorny offset < core_hdr.p_offset + core_hdr.p_filesz;) { 25731.130Smgorny Elf64_Nhdr note_hdr; 25741.130Smgorny char name_buf[64]; 25751.130Smgorny 25761.130Smgorny switch (gelf_getclass(core_elf)) { 25771.130Smgorny case ELFCLASS64: 25781.130Smgorny SYSCALL_REQUIRE(pread(core_fd, ¬e_hdr, 25791.130Smgorny sizeof(note_hdr), offset) 25801.130Smgorny == sizeof(note_hdr)); 25811.130Smgorny offset += sizeof(note_hdr); 25821.130Smgorny break; 25831.130Smgorny case ELFCLASS32: 25841.130Smgorny { 25851.130Smgorny Elf32_Nhdr tmp_hdr; 25861.130Smgorny SYSCALL_REQUIRE(pread(core_fd, &tmp_hdr, 25871.130Smgorny sizeof(tmp_hdr), offset) 25881.130Smgorny == sizeof(tmp_hdr)); 25891.130Smgorny offset += sizeof(tmp_hdr); 25901.130Smgorny note_hdr.n_namesz = tmp_hdr.n_namesz; 25911.130Smgorny note_hdr.n_descsz = tmp_hdr.n_descsz; 25921.130Smgorny note_hdr.n_type = tmp_hdr.n_type; 25931.130Smgorny } 25941.130Smgorny break; 25951.130Smgorny } 25961.130Smgorny 25971.130Smgorny /* indicates end of notes */ 25981.130Smgorny if (note_hdr.n_namesz == 0 || note_hdr.n_descsz == 0) 25991.130Smgorny break; 26001.172Sthorpej if (((prefix_match && 26011.172Sthorpej note_hdr.n_namesz > name_len) || 26021.172Sthorpej (!prefix_match && 26031.172Sthorpej note_hdr.n_namesz == name_len)) && 26041.130Smgorny note_hdr.n_namesz <= sizeof(name_buf)) { 26051.130Smgorny SYSCALL_REQUIRE(pread(core_fd, name_buf, 26061.130Smgorny note_hdr.n_namesz, offset) 26071.131Skamil == (ssize_t)(size_t)note_hdr.n_namesz); 26081.130Smgorny 26091.130Smgorny if (!strncmp(note_name, name_buf, name_len) && 26101.130Smgorny note_hdr.n_type == note_type) 26111.130Smgorny ret = note_hdr.n_descsz; 26121.130Smgorny } 26131.130Smgorny 26141.130Smgorny offset += note_hdr.n_namesz; 26151.130Smgorny /* fix to alignment */ 26161.146Smgorny offset = roundup(offset, core_hdr.p_align); 26171.130Smgorny 26181.130Smgorny /* if name & type matched above */ 26191.130Smgorny if (ret != -1) { 26201.130Smgorny ssize_t read_len = MIN(buf_len, 26211.130Smgorny note_hdr.n_descsz); 26221.130Smgorny SYSCALL_REQUIRE(pread(core_fd, buf, 26231.130Smgorny read_len, offset) == read_len); 26241.130Smgorny break; 26251.130Smgorny } 26261.130Smgorny 26271.130Smgorny offset += note_hdr.n_descsz; 26281.146Smgorny /* fix to alignment */ 26291.146Smgorny offset = roundup(offset, core_hdr.p_align); 26301.130Smgorny } 26311.130Smgorny } 26321.130Smgorny 26331.130Smgorny elf_end(core_elf); 26341.130Smgorny close(core_fd); 26351.130Smgorny 26361.130Smgorny return ret; 26371.130Smgorny} 26381.130Smgorny 26391.130SmgornyATF_TC(core_dump_procinfo); 26401.130SmgornyATF_TC_HEAD(core_dump_procinfo, tc) 26411.130Smgorny{ 26421.130Smgorny atf_tc_set_md_var(tc, "descr", 26431.130Smgorny "Trigger a core dump and verify its contents."); 26441.130Smgorny} 26451.130Smgorny 26461.130SmgornyATF_TC_BODY(core_dump_procinfo, tc) 26471.130Smgorny{ 26481.130Smgorny const int exitval = 5; 26491.130Smgorny pid_t child, wpid; 26501.130Smgorny#if defined(TWAIT_HAVE_STATUS) 26511.130Smgorny const int sigval = SIGTRAP; 26521.130Smgorny int status; 26531.130Smgorny#endif 26541.130Smgorny char core_path[] = "/tmp/core.XXXXXX"; 26551.130Smgorny int core_fd; 26561.130Smgorny struct netbsd_elfcore_procinfo procinfo; 26571.130Smgorny 26581.130Smgorny DPRINTF("Before forking process PID=%d\n", getpid()); 26591.130Smgorny SYSCALL_REQUIRE((child = fork()) != -1); 26601.130Smgorny if (child == 0) { 26611.130Smgorny DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 26621.130Smgorny FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 26631.130Smgorny 26641.130Smgorny DPRINTF("Before triggering SIGTRAP\n"); 26651.130Smgorny trigger_trap(); 26661.130Smgorny 26671.130Smgorny DPRINTF("Before exiting of the child process\n"); 26681.130Smgorny _exit(exitval); 26691.130Smgorny } 26701.130Smgorny DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 26711.130Smgorny 26721.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 26731.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 26741.130Smgorny 26751.130Smgorny validate_status_stopped(status, sigval); 26761.130Smgorny 26771.130Smgorny SYSCALL_REQUIRE((core_fd = mkstemp(core_path)) != -1); 26781.130Smgorny close(core_fd); 26791.130Smgorny 26801.130Smgorny DPRINTF("Call DUMPCORE for the child process\n"); 26811.130Smgorny SYSCALL_REQUIRE(ptrace(PT_DUMPCORE, child, core_path, strlen(core_path)) 26821.130Smgorny != -1); 26831.130Smgorny 26841.130Smgorny DPRINTF("Read core file\n"); 26851.130Smgorny ATF_REQUIRE_EQ(core_find_note(core_path, "NetBSD-CORE", 26861.130Smgorny ELF_NOTE_NETBSD_CORE_PROCINFO, &procinfo, sizeof(procinfo)), 26871.130Smgorny sizeof(procinfo)); 26881.130Smgorny 26891.130Smgorny ATF_CHECK_EQ(procinfo.cpi_version, 1); 26901.130Smgorny ATF_CHECK_EQ(procinfo.cpi_cpisize, sizeof(procinfo)); 26911.130Smgorny ATF_CHECK_EQ(procinfo.cpi_signo, SIGTRAP); 26921.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pid, child); 26931.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ppid, getpid()); 26941.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pgrp, getpgid(child)); 26951.130Smgorny ATF_CHECK_EQ(procinfo.cpi_sid, getsid(child)); 26961.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ruid, getuid()); 26971.130Smgorny ATF_CHECK_EQ(procinfo.cpi_euid, geteuid()); 26981.130Smgorny ATF_CHECK_EQ(procinfo.cpi_rgid, getgid()); 26991.130Smgorny ATF_CHECK_EQ(procinfo.cpi_egid, getegid()); 27001.130Smgorny ATF_CHECK_EQ(procinfo.cpi_nlwps, 1); 27011.173Skamil ATF_CHECK(procinfo.cpi_siglwp > 0); 27021.130Smgorny 27031.130Smgorny unlink(core_path); 27041.130Smgorny 27051.130Smgorny DPRINTF("Before resuming the child process where it left off and " 27061.130Smgorny "without signal to be sent\n"); 27071.130Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 27081.130Smgorny 27091.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 27101.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 27111.130Smgorny 27121.130Smgorny validate_status_exited(status, exitval); 27131.130Smgorny 27141.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 27151.130Smgorny TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 27161.130Smgorny} 27171.130Smgorny 27181.130Smgorny/// ---------------------------------------------------------------------------- 27191.130Smgorny 27201.138Smgorny#if defined(TWAIT_HAVE_STATUS) 27211.138Smgorny 27221.160Smgorny#define THREAD_CONCURRENT_BREAKPOINT_NUM 50 27231.156Smgorny#define THREAD_CONCURRENT_SIGNALS_NUM 50 27241.161Smgorny#define THREAD_CONCURRENT_WATCHPOINT_NUM 50 27251.138Smgorny 27261.138Smgorny/* List of signals to use for the test */ 27271.138Smgornyconst int thread_concurrent_signals_list[] = { 27281.138Smgorny SIGIO, 27291.138Smgorny SIGXCPU, 27301.138Smgorny SIGXFSZ, 27311.138Smgorny SIGVTALRM, 27321.138Smgorny SIGPROF, 27331.138Smgorny SIGWINCH, 27341.138Smgorny SIGINFO, 27351.138Smgorny SIGUSR1, 27361.138Smgorny SIGUSR2 27371.138Smgorny}; 27381.138Smgorny 27391.157Smgornyenum thread_concurrent_signal_handling { 27401.157Smgorny /* the signal is discarded by debugger */ 27411.157Smgorny TCSH_DISCARD, 27421.157Smgorny /* the handler is set to SIG_IGN */ 27431.157Smgorny TCSH_SIG_IGN, 27441.157Smgorny /* an actual handler is used */ 27451.157Smgorny TCSH_HANDLER 27461.157Smgorny}; 27471.157Smgorny 27481.156Smgornystatic pthread_barrier_t thread_concurrent_barrier; 27491.158Smgornystatic pthread_key_t thread_concurrent_key; 27501.161Smgornystatic uint32_t thread_concurrent_watchpoint_var = 0; 27511.138Smgorny 27521.160Smgornystatic void * 27531.160Smgornythread_concurrent_breakpoint_thread(void *arg) 27541.160Smgorny{ 27551.160Smgorny static volatile int watchme = 1; 27561.160Smgorny pthread_barrier_wait(&thread_concurrent_barrier); 27571.160Smgorny DPRINTF("Before entering breakpoint func from LWP %d\n", _lwp_self()); 27581.160Smgorny check_happy(watchme); 27591.160Smgorny return NULL; 27601.160Smgorny} 27611.160Smgorny 27621.157Smgornystatic void 27631.157Smgornythread_concurrent_sig_handler(int sig) 27641.157Smgorny{ 27651.158Smgorny void *tls_val = pthread_getspecific(thread_concurrent_key); 27661.158Smgorny DPRINTF("Before increment, LWP %d tls_val=%p\n", _lwp_self(), tls_val); 27671.158Smgorny FORKEE_ASSERT(pthread_setspecific(thread_concurrent_key, 27681.158Smgorny (void*)((uintptr_t)tls_val + 1)) == 0); 27691.157Smgorny} 27701.157Smgorny 27711.138Smgornystatic void * 27721.138Smgornythread_concurrent_signals_thread(void *arg) 27731.138Smgorny{ 27741.138Smgorny int sigval = thread_concurrent_signals_list[ 27751.138Smgorny _lwp_self() % __arraycount(thread_concurrent_signals_list)]; 27761.158Smgorny enum thread_concurrent_signal_handling *signal_handle = arg; 27771.158Smgorny void *tls_val; 27781.158Smgorny 27791.156Smgorny pthread_barrier_wait(&thread_concurrent_barrier); 27801.138Smgorny DPRINTF("Before raising %s from LWP %d\n", strsignal(sigval), 27811.138Smgorny _lwp_self()); 27821.138Smgorny pthread_kill(pthread_self(), sigval); 27831.158Smgorny if (*signal_handle == TCSH_HANDLER) { 27841.158Smgorny tls_val = pthread_getspecific(thread_concurrent_key); 27851.158Smgorny DPRINTF("After raising, LWP %d tls_val=%p\n", _lwp_self(), tls_val); 27861.158Smgorny FORKEE_ASSERT(tls_val == (void*)1); 27871.158Smgorny } 27881.138Smgorny return NULL; 27891.138Smgorny} 27901.138Smgorny 27911.161Smgornystatic void * 27921.161Smgornythread_concurrent_watchpoint_thread(void *arg) 27931.161Smgorny{ 27941.161Smgorny pthread_barrier_wait(&thread_concurrent_barrier); 27951.161Smgorny DPRINTF("Before modifying var from LWP %d\n", _lwp_self()); 27961.161Smgorny thread_concurrent_watchpoint_var = 1; 27971.161Smgorny return NULL; 27981.161Smgorny} 27991.161Smgorny 28001.160Smgorny#if defined(__i386__) || defined(__x86_64__) 28011.160Smgornyenum thread_concurrent_sigtrap_event { 28021.160Smgorny TCSE_UNKNOWN, 28031.161Smgorny TCSE_BREAKPOINT, 28041.161Smgorny TCSE_WATCHPOINT 28051.160Smgorny}; 28061.160Smgorny 28071.160Smgornystatic void 28081.160Smgornythread_concurrent_lwp_setup(pid_t child, lwpid_t lwpid); 28091.160Smgornystatic enum thread_concurrent_sigtrap_event 28101.160Smgornythread_concurrent_handle_sigtrap(pid_t child, ptrace_siginfo_t *info); 28111.160Smgorny#endif 28121.160Smgorny 28131.156Smgornystatic void 28141.157Smgornythread_concurrent_test(enum thread_concurrent_signal_handling signal_handle, 28151.161Smgorny int breakpoint_threads, int signal_threads, int watchpoint_threads) 28161.138Smgorny{ 28171.138Smgorny const int exitval = 5; 28181.138Smgorny const int sigval = SIGSTOP; 28191.138Smgorny pid_t child, wpid; 28201.138Smgorny int status; 28211.141Skamil struct lwp_event_count signal_counts[THREAD_CONCURRENT_SIGNALS_NUM] 28221.141Skamil = {{0, 0}}; 28231.160Smgorny struct lwp_event_count bp_counts[THREAD_CONCURRENT_BREAKPOINT_NUM] 28241.160Smgorny = {{0, 0}}; 28251.161Smgorny struct lwp_event_count wp_counts[THREAD_CONCURRENT_BREAKPOINT_NUM] 28261.161Smgorny = {{0, 0}}; 28271.159Smgorny ptrace_event_t event; 28281.156Smgorny int i; 28291.156Smgorny 28301.164Skamil#if defined(HAVE_DBREGS) 28311.164Skamil if (!can_we_set_dbregs()) { 28321.164Skamil atf_tc_skip("Either run this test as root or set sysctl(3) " 28331.164Skamil "security.models.extensions.user_set_dbregs to 1"); 28341.164Skamil } 28351.164Skamil#endif 28361.164Skamil 28371.164Skamil atf_tc_skip("PR kern/54960"); 28381.157Smgorny 28391.156Smgorny /* Protect against out-of-bounds array access. */ 28401.160Smgorny ATF_REQUIRE(breakpoint_threads <= THREAD_CONCURRENT_BREAKPOINT_NUM); 28411.156Smgorny ATF_REQUIRE(signal_threads <= THREAD_CONCURRENT_SIGNALS_NUM); 28421.161Smgorny ATF_REQUIRE(watchpoint_threads <= THREAD_CONCURRENT_WATCHPOINT_NUM); 28431.138Smgorny 28441.138Smgorny DPRINTF("Before forking process PID=%d\n", getpid()); 28451.138Smgorny SYSCALL_REQUIRE((child = fork()) != -1); 28461.138Smgorny if (child == 0) { 28471.160Smgorny pthread_t bp_threads[THREAD_CONCURRENT_BREAKPOINT_NUM]; 28481.156Smgorny pthread_t sig_threads[THREAD_CONCURRENT_SIGNALS_NUM]; 28491.161Smgorny pthread_t wp_threads[THREAD_CONCURRENT_WATCHPOINT_NUM]; 28501.138Smgorny 28511.138Smgorny DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 28521.138Smgorny FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 28531.138Smgorny 28541.138Smgorny DPRINTF("Before raising %s from child\n", strsignal(sigval)); 28551.138Smgorny FORKEE_ASSERT(raise(sigval) == 0); 28561.138Smgorny 28571.157Smgorny if (signal_handle != TCSH_DISCARD) { 28581.157Smgorny struct sigaction sa; 28591.157Smgorny unsigned int j; 28601.157Smgorny 28611.157Smgorny memset(&sa, 0, sizeof(sa)); 28621.157Smgorny if (signal_handle == TCSH_SIG_IGN) 28631.157Smgorny sa.sa_handler = SIG_IGN; 28641.157Smgorny else 28651.157Smgorny sa.sa_handler = thread_concurrent_sig_handler; 28661.157Smgorny sigemptyset(&sa.sa_mask); 28671.157Smgorny 28681.157Smgorny for (j = 0; 28691.157Smgorny j < __arraycount(thread_concurrent_signals_list); 28701.157Smgorny j++) 28711.157Smgorny FORKEE_ASSERT(sigaction( 28721.157Smgorny thread_concurrent_signals_list[j], &sa, NULL) 28731.157Smgorny != -1); 28741.157Smgorny } 28751.157Smgorny 28761.138Smgorny DPRINTF("Before starting threads from the child\n"); 28771.138Smgorny FORKEE_ASSERT(pthread_barrier_init( 28781.156Smgorny &thread_concurrent_barrier, NULL, 28791.161Smgorny breakpoint_threads + signal_threads + watchpoint_threads) 28801.161Smgorny == 0); 28811.158Smgorny FORKEE_ASSERT(pthread_key_create(&thread_concurrent_key, NULL) 28821.158Smgorny == 0); 28831.138Smgorny 28841.156Smgorny for (i = 0; i < signal_threads; i++) { 28851.156Smgorny FORKEE_ASSERT(pthread_create(&sig_threads[i], NULL, 28861.158Smgorny thread_concurrent_signals_thread, 28871.158Smgorny &signal_handle) == 0); 28881.138Smgorny } 28891.160Smgorny for (i = 0; i < breakpoint_threads; i++) { 28901.160Smgorny FORKEE_ASSERT(pthread_create(&bp_threads[i], NULL, 28911.160Smgorny thread_concurrent_breakpoint_thread, NULL) == 0); 28921.160Smgorny } 28931.161Smgorny for (i = 0; i < watchpoint_threads; i++) { 28941.161Smgorny FORKEE_ASSERT(pthread_create(&wp_threads[i], NULL, 28951.161Smgorny thread_concurrent_watchpoint_thread, NULL) == 0); 28961.161Smgorny } 28971.138Smgorny 28981.138Smgorny DPRINTF("Before joining threads from the child\n"); 28991.161Smgorny for (i = 0; i < watchpoint_threads; i++) { 29001.161Smgorny FORKEE_ASSERT(pthread_join(wp_threads[i], NULL) == 0); 29011.161Smgorny } 29021.160Smgorny for (i = 0; i < breakpoint_threads; i++) { 29031.160Smgorny FORKEE_ASSERT(pthread_join(bp_threads[i], NULL) == 0); 29041.160Smgorny } 29051.156Smgorny for (i = 0; i < signal_threads; i++) { 29061.156Smgorny FORKEE_ASSERT(pthread_join(sig_threads[i], NULL) == 0); 29071.138Smgorny } 29081.138Smgorny 29091.158Smgorny FORKEE_ASSERT(pthread_key_delete(thread_concurrent_key) == 0); 29101.138Smgorny FORKEE_ASSERT(pthread_barrier_destroy( 29111.156Smgorny &thread_concurrent_barrier) == 0); 29121.138Smgorny 29131.138Smgorny DPRINTF("Before exiting of the child process\n"); 29141.138Smgorny _exit(exitval); 29151.138Smgorny } 29161.138Smgorny DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 29171.138Smgorny 29181.138Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29191.138Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 29201.138Smgorny 29211.138Smgorny validate_status_stopped(status, sigval); 29221.138Smgorny 29231.159Smgorny DPRINTF("Set LWP event mask for the child process\n"); 29241.159Smgorny memset(&event, 0, sizeof(event)); 29251.159Smgorny event.pe_set_event |= PTRACE_LWP_CREATE; 29261.159Smgorny SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, sizeof(event)) 29271.159Smgorny != -1); 29281.159Smgorny 29291.138Smgorny DPRINTF("Before resuming the child process where it left off\n"); 29301.138Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 29311.138Smgorny 29321.138Smgorny DPRINTF("Before entering signal collection loop\n"); 29331.138Smgorny while (1) { 29341.138Smgorny ptrace_siginfo_t info; 29351.138Smgorny 29361.138Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 29371.138Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), 29381.138Smgorny child); 29391.138Smgorny if (WIFEXITED(status)) 29401.138Smgorny break; 29411.138Smgorny /* Note: we use validate_status_stopped() to get nice error 29421.138Smgorny * message. Signal is irrelevant since it won't be reached. 29431.138Smgorny */ 29441.138Smgorny else if (!WIFSTOPPED(status)) 29451.138Smgorny validate_status_stopped(status, 0); 29461.138Smgorny 29471.138Smgorny DPRINTF("Before calling PT_GET_SIGINFO\n"); 29481.138Smgorny SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 29491.138Smgorny sizeof(info)) != -1); 29501.138Smgorny 29511.138Smgorny DPRINTF("Received signal %d from LWP %d (wait: %d)\n", 29521.138Smgorny info.psi_siginfo.si_signo, info.psi_lwpid, 29531.138Smgorny WSTOPSIG(status)); 29541.138Smgorny 29551.159Smgorny ATF_CHECK_EQ_MSG(info.psi_siginfo.si_signo, WSTOPSIG(status), 29561.159Smgorny "lwp=%d, WSTOPSIG=%d, psi_siginfo=%d", info.psi_lwpid, 29571.159Smgorny WSTOPSIG(status), info.psi_siginfo.si_signo); 29581.159Smgorny 29591.159Smgorny if (WSTOPSIG(status) != SIGTRAP) { 29601.159Smgorny int expected_sig = 29611.159Smgorny thread_concurrent_signals_list[info.psi_lwpid % 29621.159Smgorny __arraycount(thread_concurrent_signals_list)]; 29631.159Smgorny ATF_CHECK_EQ_MSG(WSTOPSIG(status), expected_sig, 29641.159Smgorny "lwp=%d, expected %d, got %d", info.psi_lwpid, 29651.159Smgorny expected_sig, WSTOPSIG(status)); 29661.138Smgorny 29671.159Smgorny *FIND_EVENT_COUNT(signal_counts, info.psi_lwpid) += 1; 29681.160Smgorny } else if (info.psi_siginfo.si_code == TRAP_LWP) { 29691.160Smgorny#if defined(__i386__) || defined(__x86_64__) 29701.160Smgorny thread_concurrent_lwp_setup(child, info.psi_lwpid); 29711.160Smgorny#endif 29721.159Smgorny } else { 29731.160Smgorny#if defined(__i386__) || defined(__x86_64__) 29741.160Smgorny switch (thread_concurrent_handle_sigtrap(child, &info)) { 29751.160Smgorny case TCSE_UNKNOWN: 29761.160Smgorny /* already reported inside the function */ 29771.160Smgorny break; 29781.160Smgorny case TCSE_BREAKPOINT: 29791.160Smgorny *FIND_EVENT_COUNT(bp_counts, 29801.160Smgorny info.psi_lwpid) += 1; 29811.160Smgorny break; 29821.161Smgorny case TCSE_WATCHPOINT: 29831.161Smgorny *FIND_EVENT_COUNT(wp_counts, 29841.161Smgorny info.psi_lwpid) += 1; 29851.161Smgorny break; 29861.160Smgorny } 29871.160Smgorny#else 29881.160Smgorny ATF_CHECK_MSG(0, "Unexpected SIGTRAP, si_code=%d\n", 29891.160Smgorny info.psi_siginfo.si_code); 29901.160Smgorny#endif 29911.159Smgorny } 29921.138Smgorny 29931.138Smgorny DPRINTF("Before resuming the child process\n"); 29941.157Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 29951.159Smgorny signal_handle != TCSH_DISCARD && WSTOPSIG(status) != SIGTRAP 29961.159Smgorny ? WSTOPSIG(status) : 0) != -1); 29971.138Smgorny } 29981.138Smgorny 29991.156Smgorny for (i = 0; i < signal_threads; i++) 30001.141Skamil ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 1, 30011.141Skamil "signal_counts[%d].lec_count=%d; lec_lwp=%d", 30021.141Skamil i, signal_counts[i].lec_count, signal_counts[i].lec_lwp); 30031.156Smgorny for (i = signal_threads; i < THREAD_CONCURRENT_SIGNALS_NUM; i++) 30041.156Smgorny ATF_CHECK_EQ_MSG(signal_counts[i].lec_count, 0, 30051.156Smgorny "extraneous signal_counts[%d].lec_count=%d; lec_lwp=%d", 30061.156Smgorny i, signal_counts[i].lec_count, signal_counts[i].lec_lwp); 30071.138Smgorny 30081.160Smgorny for (i = 0; i < breakpoint_threads; i++) 30091.160Smgorny ATF_CHECK_EQ_MSG(bp_counts[i].lec_count, 1, 30101.160Smgorny "bp_counts[%d].lec_count=%d; lec_lwp=%d", 30111.160Smgorny i, bp_counts[i].lec_count, bp_counts[i].lec_lwp); 30121.160Smgorny for (i = breakpoint_threads; i < THREAD_CONCURRENT_BREAKPOINT_NUM; i++) 30131.160Smgorny ATF_CHECK_EQ_MSG(bp_counts[i].lec_count, 0, 30141.160Smgorny "extraneous bp_counts[%d].lec_count=%d; lec_lwp=%d", 30151.160Smgorny i, bp_counts[i].lec_count, bp_counts[i].lec_lwp); 30161.160Smgorny 30171.161Smgorny for (i = 0; i < watchpoint_threads; i++) 30181.161Smgorny ATF_CHECK_EQ_MSG(wp_counts[i].lec_count, 1, 30191.161Smgorny "wp_counts[%d].lec_count=%d; lec_lwp=%d", 30201.161Smgorny i, wp_counts[i].lec_count, wp_counts[i].lec_lwp); 30211.161Smgorny for (i = watchpoint_threads; i < THREAD_CONCURRENT_WATCHPOINT_NUM; i++) 30221.161Smgorny ATF_CHECK_EQ_MSG(wp_counts[i].lec_count, 0, 30231.161Smgorny "extraneous wp_counts[%d].lec_count=%d; lec_lwp=%d", 30241.161Smgorny i, wp_counts[i].lec_count, wp_counts[i].lec_lwp); 30251.161Smgorny 30261.138Smgorny validate_status_exited(status, exitval); 30271.138Smgorny} 30281.138Smgorny 30291.161Smgorny#define THREAD_CONCURRENT_TEST(test, sig_hdl, bps, sigs, wps, descr) \ 30301.156SmgornyATF_TC(test); \ 30311.156SmgornyATF_TC_HEAD(test, tc) \ 30321.156Smgorny{ \ 30331.156Smgorny atf_tc_set_md_var(tc, "descr", descr); \ 30341.156Smgorny} \ 30351.156Smgorny \ 30361.156SmgornyATF_TC_BODY(test, tc) \ 30371.156Smgorny{ \ 30381.161Smgorny thread_concurrent_test(sig_hdl, bps, sigs, wps); \ 30391.156Smgorny} 30401.156Smgorny 30411.157SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_signals, TCSH_DISCARD, 30421.161Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, 0, 30431.157Smgorny "Verify that concurrent signals issued to a single thread are reported " 30441.157Smgorny "correctly"); 30451.157SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_signals_sig_ign, TCSH_SIG_IGN, 30461.161Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, 0, 30471.157Smgorny "Verify that concurrent signals issued to a single thread are reported " 30481.157Smgorny "correctly and passed back to SIG_IGN handler"); 30491.157SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_signals_handler, TCSH_HANDLER, 30501.161Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, 0, 30511.157Smgorny "Verify that concurrent signals issued to a single thread are reported " 30521.157Smgorny "correctly and passed back to a handler function"); 30531.156Smgorny 30541.163Skamil#if defined(__i386__) || defined(__x86_64__) 30551.160SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_breakpoints, TCSH_DISCARD, 30561.161Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, 0, 0, 30571.161Smgorny "Verify that concurrent breakpoints are reported correctly"); 30581.161SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_watchpoints, TCSH_DISCARD, 30591.161Smgorny 0, 0, THREAD_CONCURRENT_WATCHPOINT_NUM, 30601.160Smgorny "Verify that concurrent breakpoints are reported correctly"); 30611.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp, TCSH_DISCARD, 30621.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, 0, THREAD_CONCURRENT_WATCHPOINT_NUM, 30631.162Smgorny "Verify that concurrent breakpoints and watchpoints are reported " 30641.162Smgorny "correctly"); 30651.162Smgorny 30661.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_sig, TCSH_DISCARD, 30671.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0, 30681.162Smgorny "Verify that concurrent breakpoints and signals are reported correctly"); 30691.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_sig_sig_ign, TCSH_SIG_IGN, 30701.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0, 30711.162Smgorny "Verify that concurrent breakpoints and signals are reported correctly " 30721.162Smgorny "and passed back to SIG_IGN handler"); 30731.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_sig_handler, TCSH_HANDLER, 30741.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 0, 30751.162Smgorny "Verify that concurrent breakpoints and signals are reported correctly " 30761.162Smgorny "and passed back to a handler function"); 30771.162Smgorny 30781.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_wp_sig, TCSH_DISCARD, 30791.162Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM, 30801.162Smgorny "Verify that concurrent watchpoints and signals are reported correctly"); 30811.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_wp_sig_sig_ign, TCSH_SIG_IGN, 30821.162Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM, 30831.162Smgorny "Verify that concurrent watchpoints and signals are reported correctly " 30841.162Smgorny "and passed back to SIG_IGN handler"); 30851.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_wp_sig_handler, TCSH_HANDLER, 30861.162Smgorny 0, THREAD_CONCURRENT_SIGNALS_NUM, THREAD_CONCURRENT_WATCHPOINT_NUM, 30871.162Smgorny "Verify that concurrent watchpoints and signals are reported correctly " 30881.162Smgorny "and passed back to a handler function"); 30891.162Smgorny 30901.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig, TCSH_DISCARD, 30911.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 30921.162Smgorny THREAD_CONCURRENT_WATCHPOINT_NUM, 30931.162Smgorny "Verify that concurrent breakpoints, watchpoints and signals are reported " 30941.162Smgorny "correctly"); 30951.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig_sig_ign, TCSH_SIG_IGN, 30961.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 30971.162Smgorny THREAD_CONCURRENT_WATCHPOINT_NUM, 30981.162Smgorny "Verify that concurrent breakpoints, watchpoints and signals are reported " 30991.162Smgorny "correctly and passed back to SIG_IGN handler"); 31001.162SmgornyTHREAD_CONCURRENT_TEST(thread_concurrent_bp_wp_sig_handler, TCSH_HANDLER, 31011.162Smgorny THREAD_CONCURRENT_BREAKPOINT_NUM, THREAD_CONCURRENT_SIGNALS_NUM, 31021.162Smgorny THREAD_CONCURRENT_WATCHPOINT_NUM, 31031.162Smgorny "Verify that concurrent breakpoints, watchpoints and signals are reported " 31041.162Smgorny "correctly and passed back to a handler function"); 31051.163Skamil#endif 31061.160Smgorny 31071.138Smgorny#endif /*defined(TWAIT_HAVE_STATUS)*/ 31081.138Smgorny 31091.138Smgorny/// ---------------------------------------------------------------------------- 31101.138Smgorny 31111.174Skamil#include "t_ptrace_register_wait.h" 31121.175Skamil#include "t_ptrace_syscall_wait.h" 31131.176Skamil#include "t_ptrace_step_wait.h" 31141.177Skamil#include "t_ptrace_kill_wait.h" 31151.178Skamil#include "t_ptrace_bytetransfer_wait.h" 31161.179Skamil#include "t_ptrace_clone_wait.h" 31171.180Skamil#include "t_ptrace_fork_wait.h" 31181.181Skamil#include "t_ptrace_signal_wait.h" 31191.183Skamil#include "t_ptrace_eventmask_wait.h" 31201.174Skamil 31211.174Skamil/// ---------------------------------------------------------------------------- 31221.174Skamil 31231.1Skamil#include "t_ptrace_amd64_wait.h" 31241.1Skamil#include "t_ptrace_i386_wait.h" 31251.1Skamil#include "t_ptrace_x86_wait.h" 31261.1Skamil 31271.165Skamil/// ---------------------------------------------------------------------------- 31281.165Skamil 31291.165Skamil#else 31301.165SkamilATF_TC(dummy); 31311.165SkamilATF_TC_HEAD(dummy, tc) 31321.165Skamil{ 31331.165Skamil atf_tc_set_md_var(tc, "descr", "A dummy test"); 31341.165Skamil} 31351.165Skamil 31361.165SkamilATF_TC_BODY(dummy, tc) 31371.165Skamil{ 31381.165Skamil 31391.165Skamil // Dummy, skipped 31401.165Skamil // The ATF framework requires at least a single defined test. 31411.165Skamil} 31421.165Skamil#endif 31431.165Skamil 31441.1SkamilATF_TP_ADD_TCS(tp) 31451.1Skamil{ 31461.1Skamil setvbuf(stdout, NULL, _IONBF, 0); 31471.1Skamil setvbuf(stderr, NULL, _IONBF, 0); 31481.33Skamil 31491.165Skamil#ifdef ENABLE_TESTS 31501.37Skamil ATF_TP_ADD_TC(tp, traceme_pid1_parent); 31511.37Skamil 31521.43Skamil ATF_TP_ADD_TC(tp, traceme_vfork_exec); 31531.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalmasked_exec); 31541.96Skamil ATF_TP_ADD_TC(tp, traceme_vfork_signalignored_exec); 31551.43Skamil 31561.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sees_terminaton_before_the_parent); 31571.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_sysctl_lookup_without_duplicates); 31581.61Skre ATF_TP_ADD_TC_HAVE_PID(tp, 31591.61Skre unrelated_tracer_sees_terminaton_before_the_parent); 31601.67Skamil ATF_TP_ADD_TC_HAVE_PID(tp, tracer_attach_to_unrelated_stopped_process); 31611.51Skamil 31621.51Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_child); 31631.66Skamil ATF_TP_ADD_TC(tp, parent_attach_to_its_stopped_child); 31641.51Skamil 31651.51Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_parent); 31661.65Skamil ATF_TP_ADD_TC(tp, child_attach_to_its_stopped_parent); 31671.51Skamil 31681.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 31691.51Skamil tracee_sees_its_original_parent_getppid); 31701.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 31711.51Skamil tracee_sees_its_original_parent_sysctl_kinfo_proc2); 31721.51Skamil ATF_TP_ADD_TC_HAVE_PID(tp, 31731.51Skamil tracee_sees_its_original_parent_procfs_status); 31741.1Skamil 31751.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_empty); 31761.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_fork); 31771.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork); 31781.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_vfork_done); 31791.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_create); 31801.53Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_lwp_exit); 31811.125Skamil ATF_TP_ADD_TC(tp, eventmask_preserved_posix_spawn); 31821.1Skamil 31831.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0); 31841.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1); 31851.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2); 31861.77Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3); 31871.77Skamil 31881.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus); 31891.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus); 31901.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus); 31911.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus); 31921.143Skamil 31931.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus_pl_sigmask); 31941.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus_pl_sigmask); 31951.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus_pl_sigmask); 31961.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus_pl_sigmask); 31971.143Skamil 31981.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus_pl_name); 31991.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus_pl_name); 32001.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus_pl_name); 32011.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus_pl_name); 32021.143Skamil 32031.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo0_lwpstatus_pl_private); 32041.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo1_lwpstatus_pl_private); 32051.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo2_lwpstatus_pl_private); 32061.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpinfo3_lwpstatus_pl_private); 32071.143Skamil 32081.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0); 32091.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1); 32101.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2); 32111.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3); 32121.143Skamil 32131.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0_pl_sigmask); 32141.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1_pl_sigmask); 32151.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2_pl_sigmask); 32161.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3_pl_sigmask); 32171.143Skamil 32181.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0_pl_name); 32191.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1_pl_name); 32201.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2_pl_name); 32211.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3_pl_name); 32221.143Skamil 32231.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext0_pl_private); 32241.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext1_pl_private); 32251.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext2_pl_private); 32261.143Skamil ATF_TP_ADD_TC(tp, traceme_lwpnext3_pl_private); 32271.143Skamil 32281.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo0); 32291.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo1); 32301.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo2); 32311.77Skamil ATF_TP_ADD_TC_HAVE_PID(tp, attach_lwpinfo3); 32321.1Skamil 32331.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_unmodified); 32341.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_faked); 32351.79Skamil 32361.82Skamil ATF_TP_ADD_TC(tp, traceme_exec); 32371.97Skamil ATF_TP_ADD_TC(tp, traceme_signalmasked_exec); 32381.97Skamil ATF_TP_ADD_TC(tp, traceme_signalignored_exec); 32391.1Skamil 32401.119Skamil ATF_TP_ADD_TC(tp, trace_thread_nolwpevents); 32411.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpexit); 32421.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate); 32431.119Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit); 32441.1Skamil 32451.153Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpexit_masked_sigtrap); 32461.153Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_masked_sigtrap); 32471.153Skamil ATF_TP_ADD_TC(tp, trace_thread_lwpcreate_and_exit_masked_sigtrap); 32481.153Skamil 32491.151Skamil ATF_TP_ADD_TC(tp, threads_and_exec); 32501.151Skamil 32511.154Skamil ATF_TP_ADD_TC(tp, suspend_no_deadlock); 32521.1Skamil 32531.155Skamil ATF_TP_ADD_TC(tp, resume); 32541.1Skamil 32551.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue); 32561.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall); 32571.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach); 32581.122Skamil 32591.130Smgorny ATF_TP_ADD_TC(tp, core_dump_procinfo); 32601.130Smgorny 32611.138Smgorny#if defined(TWAIT_HAVE_STATUS) 32621.138Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_signals); 32631.157Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_signals_sig_ign); 32641.157Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_signals_handler); 32651.160Smgorny#if defined(__i386__) || defined(__x86_64__) 32661.160Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_breakpoints); 32671.161Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_watchpoints); 32681.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp); 32691.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_sig); 32701.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_sig_sig_ign); 32711.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_sig_handler); 32721.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_wp_sig); 32731.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_wp_sig_sig_ign); 32741.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_wp_sig_handler); 32751.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp_sig); 32761.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp_sig_sig_ign); 32771.162Smgorny ATF_TP_ADD_TC(tp, thread_concurrent_bp_wp_sig_handler); 32781.160Smgorny#endif 32791.138Smgorny#endif 32801.138Smgorny 32811.174Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_REGISTER(); 32821.175Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_SYSCALL(); 32831.176Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_STEP(); 32841.177Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_KILL(); 32851.178Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_BYTETRANSFER(); 32861.179Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_CLONE(); 32871.180Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_FORK(); 32881.181Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_SIGNAL(); 32891.183Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_EVENTMASK(); 32901.174Skamil 32911.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64(); 32921.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_I386(); 32931.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_X86(); 32941.1Skamil 32951.165Skamil#else 32961.165Skamil ATF_TP_ADD_TC(tp, dummy); 32971.165Skamil#endif 32981.165Skamil 32991.1Skamil return atf_no_error(); 33001.1Skamil} 3301