t_ptrace_wait.c revision 1.188
11.188Skamil/* $NetBSD: t_ptrace_wait.c,v 1.188 2020/05/05 00:50:39 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.188Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.188 2020/05/05 00:50:39 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.83Skamilstatic void 1071.180Skamilptrace_siginfo(bool faked, void (*sah)(int a, siginfo_t *b, void *c), int *signal_caught) 1081.1Skamil{ 1091.180Skamil const int exitval = 5; 1101.180Skamil const int sigval = SIGINT; 1111.180Skamil const int sigfaked = SIGTRAP; 1121.180Skamil const int sicodefaked = TRAP_BRKPT; 1131.1Skamil pid_t child, wpid; 1141.180Skamil struct sigaction sa; 1151.1Skamil#if defined(TWAIT_HAVE_STATUS) 1161.1Skamil int status; 1171.1Skamil#endif 1181.83Skamil struct ptrace_siginfo info; 1191.180Skamil memset(&info, 0, sizeof(info)); 1201.83Skamil 1211.13Schristos DPRINTF("Before forking process PID=%d\n", getpid()); 1221.13Schristos SYSCALL_REQUIRE((child = fork()) != -1); 1231.1Skamil if (child == 0) { 1241.13Schristos DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1251.1Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1261.1Skamil 1271.180Skamil sa.sa_sigaction = sah; 1281.180Skamil sa.sa_flags = SA_SIGINFO; 1291.180Skamil sigemptyset(&sa.sa_mask); 1301.180Skamil 1311.180Skamil FORKEE_ASSERT(sigaction(faked ? sigfaked : sigval, &sa, NULL) 1321.180Skamil != -1); 1331.153Skamil 1341.13Schristos DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1351.1Skamil FORKEE_ASSERT(raise(sigval) == 0); 1361.1Skamil 1371.180Skamil FORKEE_ASSERT_EQ(*signal_caught, 1); 1381.1Skamil 1391.180Skamil DPRINTF("Before exiting of the child process\n"); 1401.180Skamil _exit(exitval); 1411.1Skamil } 1421.13Schristos DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1431.1Skamil 1441.13Schristos DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1451.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1461.1Skamil 1471.1Skamil validate_status_stopped(status, sigval); 1481.1Skamil 1491.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 1501.83Skamil SYSCALL_REQUIRE( 1511.83Skamil ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 1521.1Skamil 1531.83Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1541.83Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 1551.83Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1561.83Skamil info.psi_siginfo.si_errno); 1571.1Skamil 1581.180Skamil if (faked) { 1591.180Skamil DPRINTF("Before setting new faked signal to signo=%d " 1601.180Skamil "si_code=%d\n", sigfaked, sicodefaked); 1611.180Skamil info.psi_siginfo.si_signo = sigfaked; 1621.180Skamil info.psi_siginfo.si_code = sicodefaked; 1631.83Skamil } 1641.1Skamil 1651.180Skamil DPRINTF("Before calling ptrace(2) with PT_SET_SIGINFO for child\n"); 1661.180Skamil SYSCALL_REQUIRE( 1671.180Skamil ptrace(PT_SET_SIGINFO, child, &info, sizeof(info)) != -1); 1681.1Skamil 1691.180Skamil if (faked) { 1701.83Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 1711.83Skamil "child\n"); 1721.180Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 1731.180Skamil sizeof(info)) != -1); 1741.1Skamil 1751.180Skamil DPRINTF("Before checking siginfo_t\n"); 1761.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigfaked); 1771.180Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, sicodefaked); 1781.83Skamil } 1791.1Skamil 1801.180Skamil DPRINTF("Before resuming the child process where it left off and " 1811.180Skamil "without signal to be sent\n"); 1821.180Skamil SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 1831.180Skamil faked ? sigfaked : sigval) != -1); 1841.1Skamil 1851.180Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1861.1Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1871.1Skamil 1881.180Skamil validate_status_exited(status, exitval); 1891.1Skamil 1901.180Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1911.1Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 1921.1Skamil} 1931.1Skamil 1941.180Skamil#define PTRACE_SIGINFO(test, faked) \ 1951.83SkamilATF_TC(test); \ 1961.83SkamilATF_TC_HEAD(test, tc) \ 1971.83Skamil{ \ 1981.180Skamil atf_tc_set_md_var(tc, "descr", \ 1991.180Skamil "Verify basic PT_GET_SIGINFO and PT_SET_SIGINFO calls" \ 2001.180Skamil "with%s setting signal to new value", faked ? "" : "out"); \ 2011.180Skamil} \ 2021.180Skamil \ 2031.180Skamilstatic int test##_caught = 0; \ 2041.180Skamil \ 2051.180Skamilstatic void \ 2061.180Skamiltest##_sighandler(int sig, siginfo_t *info, void *ctx) \ 2071.180Skamil{ \ 2081.180Skamil if (faked) { \ 2091.180Skamil FORKEE_ASSERT_EQ(sig, SIGTRAP); \ 2101.180Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGTRAP); \ 2111.180Skamil FORKEE_ASSERT_EQ(info->si_code, TRAP_BRKPT); \ 2121.180Skamil } else { \ 2131.180Skamil FORKEE_ASSERT_EQ(sig, SIGINT); \ 2141.180Skamil FORKEE_ASSERT_EQ(info->si_signo, SIGINT); \ 2151.180Skamil FORKEE_ASSERT_EQ(info->si_code, SI_LWP); \ 2161.180Skamil } \ 2171.180Skamil \ 2181.180Skamil ++ test##_caught; \ 2191.83Skamil} \ 2201.83Skamil \ 2211.83SkamilATF_TC_BODY(test, tc) \ 2221.83Skamil{ \ 2231.83Skamil \ 2241.180Skamil ptrace_siginfo(faked, test##_sighandler, & test##_caught); \ 2251.83Skamil} 2261.83Skamil 2271.180SkamilPTRACE_SIGINFO(siginfo_set_unmodified, false) 2281.180SkamilPTRACE_SIGINFO(siginfo_set_faked, true) 2291.83Skamil 2301.83Skamil/// ---------------------------------------------------------------------------- 2311.83Skamil 2321.106Skamilstatic void 2331.122Skamiluser_va0_disable(int operation) 2341.122Skamil{ 2351.122Skamil pid_t child, wpid; 2361.122Skamil#if defined(TWAIT_HAVE_STATUS) 2371.122Skamil int status; 2381.122Skamil#endif 2391.122Skamil const int sigval = SIGSTOP; 2401.122Skamil int rv; 2411.122Skamil 2421.122Skamil struct ptrace_siginfo info; 2431.122Skamil 2441.122Skamil if (get_user_va0_disable() == 0) 2451.122Skamil atf_tc_skip("vm.user_va0_disable is set to 0"); 2461.122Skamil 2471.122Skamil memset(&info, 0, sizeof(info)); 2481.122Skamil 2491.122Skamil DPRINTF("Before forking process PID=%d\n", getpid()); 2501.122Skamil SYSCALL_REQUIRE((child = fork()) != -1); 2511.122Skamil if (child == 0) { 2521.122Skamil DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2531.122Skamil FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2541.122Skamil 2551.122Skamil DPRINTF("Before raising %s from child\n", strsignal(sigval)); 2561.122Skamil FORKEE_ASSERT(raise(sigval) == 0); 2571.122Skamil 2581.122Skamil /* NOTREACHED */ 2591.122Skamil FORKEE_ASSERTX(0 && "This shall not be reached"); 2601.122Skamil __unreachable(); 2611.122Skamil } 2621.122Skamil DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2631.122Skamil 2641.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2651.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2661.122Skamil 2671.122Skamil validate_status_stopped(status, sigval); 2681.122Skamil 2691.122Skamil DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for " 2701.122Skamil "child\n"); 2711.122Skamil SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, 2721.122Skamil sizeof(info)) != -1); 2731.122Skamil 2741.122Skamil DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 2751.122Skamil DPRINTF("Signal properties: si_signo=%#x si_code=%#x " 2761.122Skamil "si_errno=%#x\n", 2771.122Skamil info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 2781.122Skamil info.psi_siginfo.si_errno); 2791.122Skamil 2801.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 2811.122Skamil ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP); 2821.122Skamil 2831.122Skamil DPRINTF("Before resuming the child process in PC=0x0 " 2841.122Skamil "and without signal to be sent\n"); 2851.122Skamil errno = 0; 2861.122Skamil rv = ptrace(operation, child, (void *)0, 0); 2871.122Skamil ATF_REQUIRE_EQ(errno, EINVAL); 2881.122Skamil ATF_REQUIRE_EQ(rv, -1); 2891.122Skamil 2901.122Skamil SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 2911.122Skamil 2921.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2931.122Skamil TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2941.122Skamil validate_status_signaled(status, SIGKILL, 0); 2951.122Skamil 2961.122Skamil DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2971.122Skamil TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 2981.122Skamil} 2991.122Skamil 3001.122Skamil#define USER_VA0_DISABLE(test, operation) \ 3011.122SkamilATF_TC(test); \ 3021.122SkamilATF_TC_HEAD(test, tc) \ 3031.122Skamil{ \ 3041.122Skamil atf_tc_set_md_var(tc, "descr", \ 3051.122Skamil "Verify behavior of " #operation " with PC set to 0x0"); \ 3061.122Skamil} \ 3071.122Skamil \ 3081.122SkamilATF_TC_BODY(test, tc) \ 3091.122Skamil{ \ 3101.122Skamil \ 3111.122Skamil user_va0_disable(operation); \ 3121.122Skamil} 3131.122Skamil 3141.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE) 3151.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL) 3161.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH) 3171.122Skamil 3181.122Skamil/// ---------------------------------------------------------------------------- 3191.122Skamil 3201.130Smgorny/* 3211.130Smgorny * Parse the core file and find the requested note. If the reading or parsing 3221.130Smgorny * fails, the test is failed. If the note is found, it is read onto buf, up to 3231.130Smgorny * buf_len. The actual length of the note is returned (which can be greater 3241.130Smgorny * than buf_len, indicating that it has been truncated). If the note is not 3251.130Smgorny * found, -1 is returned. 3261.172Sthorpej * 3271.172Sthorpej * If the note_name ends in '*', then we find the first note that matches 3281.172Sthorpej * the note_name prefix up to the '*' character, e.g.: 3291.172Sthorpej * 3301.172Sthorpej * NetBSD-CORE@* 3311.172Sthorpej * 3321.172Sthorpej * finds the first note whose name prefix matches "NetBSD-CORE@". 3331.130Smgorny */ 3341.130Smgornystatic ssize_t core_find_note(const char *core_path, 3351.130Smgorny const char *note_name, uint64_t note_type, void *buf, size_t buf_len) 3361.130Smgorny{ 3371.130Smgorny int core_fd; 3381.130Smgorny Elf *core_elf; 3391.130Smgorny size_t core_numhdr, i; 3401.130Smgorny ssize_t ret = -1; 3411.172Sthorpej size_t name_len = strlen(note_name); 3421.172Sthorpej bool prefix_match = false; 3431.172Sthorpej 3441.172Sthorpej if (note_name[name_len - 1] == '*') { 3451.172Sthorpej prefix_match = true; 3461.172Sthorpej name_len--; 3471.172Sthorpej } else { 3481.172Sthorpej /* note: we assume note name will be null-terminated */ 3491.172Sthorpej name_len++; 3501.172Sthorpej } 3511.130Smgorny 3521.130Smgorny SYSCALL_REQUIRE((core_fd = open(core_path, O_RDONLY)) != -1); 3531.130Smgorny SYSCALL_REQUIRE(elf_version(EV_CURRENT) != EV_NONE); 3541.130Smgorny SYSCALL_REQUIRE((core_elf = elf_begin(core_fd, ELF_C_READ, NULL))); 3551.130Smgorny 3561.130Smgorny SYSCALL_REQUIRE(elf_getphnum(core_elf, &core_numhdr) != 0); 3571.130Smgorny for (i = 0; i < core_numhdr && ret == -1; i++) { 3581.130Smgorny GElf_Phdr core_hdr; 3591.130Smgorny size_t offset; 3601.130Smgorny SYSCALL_REQUIRE(gelf_getphdr(core_elf, i, &core_hdr)); 3611.130Smgorny if (core_hdr.p_type != PT_NOTE) 3621.130Smgorny continue; 3631.130Smgorny 3641.130Smgorny for (offset = core_hdr.p_offset; 3651.130Smgorny offset < core_hdr.p_offset + core_hdr.p_filesz;) { 3661.130Smgorny Elf64_Nhdr note_hdr; 3671.130Smgorny char name_buf[64]; 3681.130Smgorny 3691.130Smgorny switch (gelf_getclass(core_elf)) { 3701.130Smgorny case ELFCLASS64: 3711.130Smgorny SYSCALL_REQUIRE(pread(core_fd, ¬e_hdr, 3721.130Smgorny sizeof(note_hdr), offset) 3731.130Smgorny == sizeof(note_hdr)); 3741.130Smgorny offset += sizeof(note_hdr); 3751.130Smgorny break; 3761.130Smgorny case ELFCLASS32: 3771.130Smgorny { 3781.130Smgorny Elf32_Nhdr tmp_hdr; 3791.130Smgorny SYSCALL_REQUIRE(pread(core_fd, &tmp_hdr, 3801.130Smgorny sizeof(tmp_hdr), offset) 3811.130Smgorny == sizeof(tmp_hdr)); 3821.130Smgorny offset += sizeof(tmp_hdr); 3831.130Smgorny note_hdr.n_namesz = tmp_hdr.n_namesz; 3841.130Smgorny note_hdr.n_descsz = tmp_hdr.n_descsz; 3851.130Smgorny note_hdr.n_type = tmp_hdr.n_type; 3861.130Smgorny } 3871.130Smgorny break; 3881.130Smgorny } 3891.130Smgorny 3901.130Smgorny /* indicates end of notes */ 3911.130Smgorny if (note_hdr.n_namesz == 0 || note_hdr.n_descsz == 0) 3921.130Smgorny break; 3931.172Sthorpej if (((prefix_match && 3941.172Sthorpej note_hdr.n_namesz > name_len) || 3951.172Sthorpej (!prefix_match && 3961.172Sthorpej note_hdr.n_namesz == name_len)) && 3971.130Smgorny note_hdr.n_namesz <= sizeof(name_buf)) { 3981.130Smgorny SYSCALL_REQUIRE(pread(core_fd, name_buf, 3991.130Smgorny note_hdr.n_namesz, offset) 4001.131Skamil == (ssize_t)(size_t)note_hdr.n_namesz); 4011.130Smgorny 4021.130Smgorny if (!strncmp(note_name, name_buf, name_len) && 4031.130Smgorny note_hdr.n_type == note_type) 4041.130Smgorny ret = note_hdr.n_descsz; 4051.130Smgorny } 4061.130Smgorny 4071.130Smgorny offset += note_hdr.n_namesz; 4081.130Smgorny /* fix to alignment */ 4091.146Smgorny offset = roundup(offset, core_hdr.p_align); 4101.130Smgorny 4111.130Smgorny /* if name & type matched above */ 4121.130Smgorny if (ret != -1) { 4131.130Smgorny ssize_t read_len = MIN(buf_len, 4141.130Smgorny note_hdr.n_descsz); 4151.130Smgorny SYSCALL_REQUIRE(pread(core_fd, buf, 4161.130Smgorny read_len, offset) == read_len); 4171.130Smgorny break; 4181.130Smgorny } 4191.130Smgorny 4201.130Smgorny offset += note_hdr.n_descsz; 4211.146Smgorny /* fix to alignment */ 4221.146Smgorny offset = roundup(offset, core_hdr.p_align); 4231.130Smgorny } 4241.130Smgorny } 4251.130Smgorny 4261.130Smgorny elf_end(core_elf); 4271.130Smgorny close(core_fd); 4281.130Smgorny 4291.130Smgorny return ret; 4301.130Smgorny} 4311.130Smgorny 4321.130SmgornyATF_TC(core_dump_procinfo); 4331.130SmgornyATF_TC_HEAD(core_dump_procinfo, tc) 4341.130Smgorny{ 4351.130Smgorny atf_tc_set_md_var(tc, "descr", 4361.130Smgorny "Trigger a core dump and verify its contents."); 4371.130Smgorny} 4381.130Smgorny 4391.130SmgornyATF_TC_BODY(core_dump_procinfo, tc) 4401.130Smgorny{ 4411.130Smgorny const int exitval = 5; 4421.130Smgorny pid_t child, wpid; 4431.130Smgorny#if defined(TWAIT_HAVE_STATUS) 4441.130Smgorny const int sigval = SIGTRAP; 4451.130Smgorny int status; 4461.130Smgorny#endif 4471.130Smgorny char core_path[] = "/tmp/core.XXXXXX"; 4481.130Smgorny int core_fd; 4491.130Smgorny struct netbsd_elfcore_procinfo procinfo; 4501.130Smgorny 4511.130Smgorny DPRINTF("Before forking process PID=%d\n", getpid()); 4521.130Smgorny SYSCALL_REQUIRE((child = fork()) != -1); 4531.130Smgorny if (child == 0) { 4541.130Smgorny DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 4551.130Smgorny FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 4561.130Smgorny 4571.130Smgorny DPRINTF("Before triggering SIGTRAP\n"); 4581.130Smgorny trigger_trap(); 4591.130Smgorny 4601.130Smgorny DPRINTF("Before exiting of the child process\n"); 4611.130Smgorny _exit(exitval); 4621.130Smgorny } 4631.130Smgorny DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 4641.130Smgorny 4651.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 4661.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 4671.130Smgorny 4681.130Smgorny validate_status_stopped(status, sigval); 4691.130Smgorny 4701.130Smgorny SYSCALL_REQUIRE((core_fd = mkstemp(core_path)) != -1); 4711.130Smgorny close(core_fd); 4721.130Smgorny 4731.130Smgorny DPRINTF("Call DUMPCORE for the child process\n"); 4741.130Smgorny SYSCALL_REQUIRE(ptrace(PT_DUMPCORE, child, core_path, strlen(core_path)) 4751.130Smgorny != -1); 4761.130Smgorny 4771.130Smgorny DPRINTF("Read core file\n"); 4781.130Smgorny ATF_REQUIRE_EQ(core_find_note(core_path, "NetBSD-CORE", 4791.130Smgorny ELF_NOTE_NETBSD_CORE_PROCINFO, &procinfo, sizeof(procinfo)), 4801.130Smgorny sizeof(procinfo)); 4811.130Smgorny 4821.130Smgorny ATF_CHECK_EQ(procinfo.cpi_version, 1); 4831.130Smgorny ATF_CHECK_EQ(procinfo.cpi_cpisize, sizeof(procinfo)); 4841.130Smgorny ATF_CHECK_EQ(procinfo.cpi_signo, SIGTRAP); 4851.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pid, child); 4861.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ppid, getpid()); 4871.130Smgorny ATF_CHECK_EQ(procinfo.cpi_pgrp, getpgid(child)); 4881.130Smgorny ATF_CHECK_EQ(procinfo.cpi_sid, getsid(child)); 4891.130Smgorny ATF_CHECK_EQ(procinfo.cpi_ruid, getuid()); 4901.130Smgorny ATF_CHECK_EQ(procinfo.cpi_euid, geteuid()); 4911.130Smgorny ATF_CHECK_EQ(procinfo.cpi_rgid, getgid()); 4921.130Smgorny ATF_CHECK_EQ(procinfo.cpi_egid, getegid()); 4931.130Smgorny ATF_CHECK_EQ(procinfo.cpi_nlwps, 1); 4941.173Skamil ATF_CHECK(procinfo.cpi_siglwp > 0); 4951.130Smgorny 4961.130Smgorny unlink(core_path); 4971.130Smgorny 4981.130Smgorny DPRINTF("Before resuming the child process where it left off and " 4991.130Smgorny "without signal to be sent\n"); 5001.130Smgorny SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 5011.130Smgorny 5021.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5031.130Smgorny TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 5041.130Smgorny 5051.130Smgorny validate_status_exited(status, exitval); 5061.130Smgorny 5071.130Smgorny DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 5081.130Smgorny TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 5091.130Smgorny} 5101.130Smgorny 5111.130Smgorny/// ---------------------------------------------------------------------------- 5121.130Smgorny 5131.174Skamil#include "t_ptrace_register_wait.h" 5141.175Skamil#include "t_ptrace_syscall_wait.h" 5151.176Skamil#include "t_ptrace_step_wait.h" 5161.177Skamil#include "t_ptrace_kill_wait.h" 5171.178Skamil#include "t_ptrace_bytetransfer_wait.h" 5181.179Skamil#include "t_ptrace_clone_wait.h" 5191.180Skamil#include "t_ptrace_fork_wait.h" 5201.181Skamil#include "t_ptrace_signal_wait.h" 5211.183Skamil#include "t_ptrace_eventmask_wait.h" 5221.185Skamil#include "t_ptrace_lwp_wait.h" 5231.186Skamil#include "t_ptrace_exec_wait.h" 5241.187Skamil#include "t_ptrace_topology_wait.h" 5251.188Skamil#include "t_ptrace_threads_wait.h" 5261.174Skamil 5271.174Skamil/// ---------------------------------------------------------------------------- 5281.174Skamil 5291.1Skamil#include "t_ptrace_amd64_wait.h" 5301.1Skamil#include "t_ptrace_i386_wait.h" 5311.1Skamil#include "t_ptrace_x86_wait.h" 5321.1Skamil 5331.165Skamil/// ---------------------------------------------------------------------------- 5341.165Skamil 5351.165Skamil#else 5361.165SkamilATF_TC(dummy); 5371.165SkamilATF_TC_HEAD(dummy, tc) 5381.165Skamil{ 5391.165Skamil atf_tc_set_md_var(tc, "descr", "A dummy test"); 5401.165Skamil} 5411.165Skamil 5421.165SkamilATF_TC_BODY(dummy, tc) 5431.165Skamil{ 5441.165Skamil 5451.165Skamil // Dummy, skipped 5461.165Skamil // The ATF framework requires at least a single defined test. 5471.165Skamil} 5481.165Skamil#endif 5491.165Skamil 5501.1SkamilATF_TP_ADD_TCS(tp) 5511.1Skamil{ 5521.1Skamil setvbuf(stdout, NULL, _IONBF, 0); 5531.1Skamil setvbuf(stderr, NULL, _IONBF, 0); 5541.33Skamil 5551.165Skamil#ifdef ENABLE_TESTS 5561.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_unmodified); 5571.79Skamil ATF_TP_ADD_TC(tp, siginfo_set_faked); 5581.79Skamil 5591.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue); 5601.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall); 5611.122Skamil ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach); 5621.122Skamil 5631.130Smgorny ATF_TP_ADD_TC(tp, core_dump_procinfo); 5641.130Smgorny 5651.174Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_REGISTER(); 5661.175Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_SYSCALL(); 5671.176Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_STEP(); 5681.177Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_KILL(); 5691.178Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_BYTETRANSFER(); 5701.179Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_CLONE(); 5711.180Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_FORK(); 5721.181Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_SIGNAL(); 5731.183Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_EVENTMASK(); 5741.185Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_LWP(); 5751.186Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_EXEC(); 5761.187Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_TOPOLOGY(); 5771.188Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_THREADS(); 5781.174Skamil 5791.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64(); 5801.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_I386(); 5811.1Skamil ATF_TP_ADD_TCS_PTRACE_WAIT_X86(); 5821.1Skamil 5831.165Skamil#else 5841.165Skamil ATF_TP_ADD_TC(tp, dummy); 5851.165Skamil#endif 5861.165Skamil 5871.1Skamil return atf_no_error(); 5881.1Skamil} 589