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, &note_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