t_ptrace_wait.c revision 1.190
11.190Skamil/*	$NetBSD: t_ptrace_wait.c,v 1.190 2020/05/05 01:24:29 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.190Skamil__RCSID("$NetBSD: t_ptrace_wait.c,v 1.190 2020/05/05 01:24:29 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.122Skamiluser_va0_disable(int operation)
1081.122Skamil{
1091.122Skamil	pid_t child, wpid;
1101.122Skamil#if defined(TWAIT_HAVE_STATUS)
1111.122Skamil	int status;
1121.122Skamil#endif
1131.122Skamil	const int sigval = SIGSTOP;
1141.122Skamil	int rv;
1151.122Skamil
1161.122Skamil	struct ptrace_siginfo info;
1171.122Skamil
1181.122Skamil	if (get_user_va0_disable() == 0)
1191.122Skamil		atf_tc_skip("vm.user_va0_disable is set to 0");
1201.122Skamil
1211.122Skamil	memset(&info, 0, sizeof(info));
1221.122Skamil
1231.122Skamil	DPRINTF("Before forking process PID=%d\n", getpid());
1241.122Skamil	SYSCALL_REQUIRE((child = fork()) != -1);
1251.122Skamil	if (child == 0) {
1261.122Skamil		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1271.122Skamil		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1281.122Skamil
1291.122Skamil		DPRINTF("Before raising %s from child\n", strsignal(sigval));
1301.122Skamil		FORKEE_ASSERT(raise(sigval) == 0);
1311.122Skamil
1321.122Skamil		/* NOTREACHED */
1331.122Skamil		FORKEE_ASSERTX(0 && "This shall not be reached");
1341.122Skamil		__unreachable();
1351.122Skamil	}
1361.122Skamil	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1371.122Skamil
1381.122Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1391.122Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1401.122Skamil
1411.122Skamil	validate_status_stopped(status, sigval);
1421.122Skamil
1431.122Skamil	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
1441.122Skamil		"child\n");
1451.122Skamil	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
1461.122Skamil		sizeof(info)) != -1);
1471.122Skamil
1481.122Skamil	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1491.122Skamil	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
1501.122Skamil		"si_errno=%#x\n",
1511.122Skamil		info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1521.122Skamil		info.psi_siginfo.si_errno);
1531.122Skamil
1541.122Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
1551.122Skamil	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
1561.122Skamil
1571.122Skamil	DPRINTF("Before resuming the child process in PC=0x0 "
1581.122Skamil	    "and without signal to be sent\n");
1591.122Skamil	errno = 0;
1601.122Skamil	rv = ptrace(operation, child, (void *)0, 0);
1611.122Skamil	ATF_REQUIRE_EQ(errno, EINVAL);
1621.122Skamil	ATF_REQUIRE_EQ(rv, -1);
1631.122Skamil
1641.122Skamil	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
1651.122Skamil
1661.122Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1671.122Skamil	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1681.122Skamil	validate_status_signaled(status, SIGKILL, 0);
1691.122Skamil
1701.122Skamil	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1711.122Skamil	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1721.122Skamil}
1731.122Skamil
1741.122Skamil#define USER_VA0_DISABLE(test, operation)				\
1751.122SkamilATF_TC(test);								\
1761.122SkamilATF_TC_HEAD(test, tc)							\
1771.122Skamil{									\
1781.122Skamil	atf_tc_set_md_var(tc, "descr",					\
1791.122Skamil	    "Verify behavior of " #operation " with PC set to 0x0");	\
1801.122Skamil}									\
1811.122Skamil									\
1821.122SkamilATF_TC_BODY(test, tc)							\
1831.122Skamil{									\
1841.122Skamil									\
1851.122Skamil	user_va0_disable(operation);					\
1861.122Skamil}
1871.122Skamil
1881.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE)
1891.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL)
1901.122SkamilUSER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH)
1911.122Skamil
1921.122Skamil/// ----------------------------------------------------------------------------
1931.122Skamil
1941.174Skamil#include "t_ptrace_register_wait.h"
1951.175Skamil#include "t_ptrace_syscall_wait.h"
1961.176Skamil#include "t_ptrace_step_wait.h"
1971.177Skamil#include "t_ptrace_kill_wait.h"
1981.178Skamil#include "t_ptrace_bytetransfer_wait.h"
1991.179Skamil#include "t_ptrace_clone_wait.h"
2001.180Skamil#include "t_ptrace_fork_wait.h"
2011.181Skamil#include "t_ptrace_signal_wait.h"
2021.183Skamil#include "t_ptrace_eventmask_wait.h"
2031.185Skamil#include "t_ptrace_lwp_wait.h"
2041.186Skamil#include "t_ptrace_exec_wait.h"
2051.187Skamil#include "t_ptrace_topology_wait.h"
2061.188Skamil#include "t_ptrace_threads_wait.h"
2071.189Skamil#include "t_ptrace_siginfo_wait.h"
2081.190Skamil#include "t_ptrace_core_wait.h"
2091.174Skamil
2101.174Skamil/// ----------------------------------------------------------------------------
2111.174Skamil
2121.1Skamil#include "t_ptrace_amd64_wait.h"
2131.1Skamil#include "t_ptrace_i386_wait.h"
2141.1Skamil#include "t_ptrace_x86_wait.h"
2151.1Skamil
2161.165Skamil/// ----------------------------------------------------------------------------
2171.165Skamil
2181.165Skamil#else
2191.165SkamilATF_TC(dummy);
2201.165SkamilATF_TC_HEAD(dummy, tc)
2211.165Skamil{
2221.165Skamil	atf_tc_set_md_var(tc, "descr", "A dummy test");
2231.165Skamil}
2241.165Skamil
2251.165SkamilATF_TC_BODY(dummy, tc)
2261.165Skamil{
2271.165Skamil
2281.165Skamil	// Dummy, skipped
2291.165Skamil	// The ATF framework requires at least a single defined test.
2301.165Skamil}
2311.165Skamil#endif
2321.165Skamil
2331.1SkamilATF_TP_ADD_TCS(tp)
2341.1Skamil{
2351.1Skamil	setvbuf(stdout, NULL, _IONBF, 0);
2361.1Skamil	setvbuf(stderr, NULL, _IONBF, 0);
2371.33Skamil
2381.165Skamil#ifdef ENABLE_TESTS
2391.122Skamil	ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue);
2401.122Skamil	ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall);
2411.122Skamil	ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach);
2421.122Skamil
2431.174Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_REGISTER();
2441.175Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_SYSCALL();
2451.176Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_STEP();
2461.177Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_KILL();
2471.178Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_BYTETRANSFER();
2481.179Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_CLONE();
2491.180Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_FORK();
2501.181Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_SIGNAL();
2511.183Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_EVENTMASK();
2521.185Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_LWP();
2531.186Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_EXEC();
2541.187Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_TOPOLOGY();
2551.188Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_THREADS();
2561.189Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_SIGINFO();
2571.190Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_CORE();
2581.174Skamil
2591.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
2601.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
2611.1Skamil	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
2621.1Skamil
2631.165Skamil#else
2641.165Skamil	ATF_TP_ADD_TC(tp, dummy);
2651.165Skamil#endif
2661.165Skamil
2671.1Skamil	return atf_no_error();
2681.1Skamil}
269