t_ptrace_wait.c revision 1.190
1/*	$NetBSD: t_ptrace_wait.c,v 1.190 2020/05/05 01:24:29 kamil Exp $	*/
2
3/*-
4 * Copyright (c) 2016, 2017, 2018, 2019, 2020 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29#include <sys/cdefs.h>
30__RCSID("$NetBSD: t_ptrace_wait.c,v 1.190 2020/05/05 01:24:29 kamil Exp $");
31
32#define __LEGACY_PT_LWPINFO
33
34#include <sys/param.h>
35#include <sys/types.h>
36#include <sys/exec_elf.h>
37#include <sys/mman.h>
38#include <sys/ptrace.h>
39#include <sys/resource.h>
40#include <sys/stat.h>
41#include <sys/syscall.h>
42#include <sys/sysctl.h>
43#include <sys/uio.h>
44#include <sys/wait.h>
45#include <machine/reg.h>
46#include <assert.h>
47#include <elf.h>
48#include <err.h>
49#include <errno.h>
50#include <fcntl.h>
51#include <lwp.h>
52#include <pthread.h>
53#include <sched.h>
54#include <signal.h>
55#include <spawn.h>
56#include <stdint.h>
57#include <stdio.h>
58#include <stdlib.h>
59#include <strings.h>
60#include <time.h>
61#include <unistd.h>
62
63#if defined(__i386__) || defined(__x86_64__)
64#include <cpuid.h>
65#include <x86/cpu_extended_state.h>
66#include <x86/specialreg.h>
67#endif
68
69#include <libelf.h>
70#include <gelf.h>
71
72#include <atf-c.h>
73
74#ifdef ENABLE_TESTS
75
76/* Assumptions in the kernel code that must be kept. */
77__CTASSERT(sizeof(((struct ptrace_state *)0)->pe_report_event) ==
78    sizeof(((siginfo_t *)0)->si_pe_report_event));
79__CTASSERT(sizeof(((struct ptrace_state *)0)->pe_other_pid) ==
80    sizeof(((siginfo_t *)0)->si_pe_other_pid));
81__CTASSERT(sizeof(((struct ptrace_state *)0)->pe_lwp) ==
82    sizeof(((siginfo_t *)0)->si_pe_lwp));
83__CTASSERT(sizeof(((struct ptrace_state *)0)->pe_other_pid) ==
84    sizeof(((struct ptrace_state *)0)->pe_lwp));
85
86#include "h_macros.h"
87
88#include "t_ptrace_wait.h"
89#include "msg.h"
90
91#define SYSCALL_REQUIRE(expr) ATF_REQUIRE_MSG(expr, "%s: %s", # expr, \
92    strerror(errno))
93#define SYSCALL_REQUIRE_ERRNO(res, exp) ATF_REQUIRE_MSG(res == exp, \
94    "%d(%s) != %d", res, strerror(res), exp)
95
96static int debug = 0;
97
98#define DPRINTF(a, ...)	do  \
99	if (debug) \
100	printf("%s() %d.%d %s:%d " a, \
101	__func__, getpid(), _lwp_self(), __FILE__, __LINE__,  ##__VA_ARGS__); \
102    while (/*CONSTCOND*/0)
103
104/// ----------------------------------------------------------------------------
105
106static void
107user_va0_disable(int operation)
108{
109	pid_t child, wpid;
110#if defined(TWAIT_HAVE_STATUS)
111	int status;
112#endif
113	const int sigval = SIGSTOP;
114	int rv;
115
116	struct ptrace_siginfo info;
117
118	if (get_user_va0_disable() == 0)
119		atf_tc_skip("vm.user_va0_disable is set to 0");
120
121	memset(&info, 0, sizeof(info));
122
123	DPRINTF("Before forking process PID=%d\n", getpid());
124	SYSCALL_REQUIRE((child = fork()) != -1);
125	if (child == 0) {
126		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
127		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
128
129		DPRINTF("Before raising %s from child\n", strsignal(sigval));
130		FORKEE_ASSERT(raise(sigval) == 0);
131
132		/* NOTREACHED */
133		FORKEE_ASSERTX(0 && "This shall not be reached");
134		__unreachable();
135	}
136	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
137
138	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
139	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
140
141	validate_status_stopped(status, sigval);
142
143	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for "
144		"child\n");
145	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info,
146		sizeof(info)) != -1);
147
148	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
149	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
150		"si_errno=%#x\n",
151		info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
152		info.psi_siginfo.si_errno);
153
154	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
155	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
156
157	DPRINTF("Before resuming the child process in PC=0x0 "
158	    "and without signal to be sent\n");
159	errno = 0;
160	rv = ptrace(operation, child, (void *)0, 0);
161	ATF_REQUIRE_EQ(errno, EINVAL);
162	ATF_REQUIRE_EQ(rv, -1);
163
164	SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
165
166	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
167	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
168	validate_status_signaled(status, SIGKILL, 0);
169
170	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
171	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
172}
173
174#define USER_VA0_DISABLE(test, operation)				\
175ATF_TC(test);								\
176ATF_TC_HEAD(test, tc)							\
177{									\
178	atf_tc_set_md_var(tc, "descr",					\
179	    "Verify behavior of " #operation " with PC set to 0x0");	\
180}									\
181									\
182ATF_TC_BODY(test, tc)							\
183{									\
184									\
185	user_va0_disable(operation);					\
186}
187
188USER_VA0_DISABLE(user_va0_disable_pt_continue, PT_CONTINUE)
189USER_VA0_DISABLE(user_va0_disable_pt_syscall, PT_SYSCALL)
190USER_VA0_DISABLE(user_va0_disable_pt_detach, PT_DETACH)
191
192/// ----------------------------------------------------------------------------
193
194#include "t_ptrace_register_wait.h"
195#include "t_ptrace_syscall_wait.h"
196#include "t_ptrace_step_wait.h"
197#include "t_ptrace_kill_wait.h"
198#include "t_ptrace_bytetransfer_wait.h"
199#include "t_ptrace_clone_wait.h"
200#include "t_ptrace_fork_wait.h"
201#include "t_ptrace_signal_wait.h"
202#include "t_ptrace_eventmask_wait.h"
203#include "t_ptrace_lwp_wait.h"
204#include "t_ptrace_exec_wait.h"
205#include "t_ptrace_topology_wait.h"
206#include "t_ptrace_threads_wait.h"
207#include "t_ptrace_siginfo_wait.h"
208#include "t_ptrace_core_wait.h"
209
210/// ----------------------------------------------------------------------------
211
212#include "t_ptrace_amd64_wait.h"
213#include "t_ptrace_i386_wait.h"
214#include "t_ptrace_x86_wait.h"
215
216/// ----------------------------------------------------------------------------
217
218#else
219ATF_TC(dummy);
220ATF_TC_HEAD(dummy, tc)
221{
222	atf_tc_set_md_var(tc, "descr", "A dummy test");
223}
224
225ATF_TC_BODY(dummy, tc)
226{
227
228	// Dummy, skipped
229	// The ATF framework requires at least a single defined test.
230}
231#endif
232
233ATF_TP_ADD_TCS(tp)
234{
235	setvbuf(stdout, NULL, _IONBF, 0);
236	setvbuf(stderr, NULL, _IONBF, 0);
237
238#ifdef ENABLE_TESTS
239	ATF_TP_ADD_TC(tp, user_va0_disable_pt_continue);
240	ATF_TP_ADD_TC(tp, user_va0_disable_pt_syscall);
241	ATF_TP_ADD_TC(tp, user_va0_disable_pt_detach);
242
243	ATF_TP_ADD_TCS_PTRACE_WAIT_REGISTER();
244	ATF_TP_ADD_TCS_PTRACE_WAIT_SYSCALL();
245	ATF_TP_ADD_TCS_PTRACE_WAIT_STEP();
246	ATF_TP_ADD_TCS_PTRACE_WAIT_KILL();
247	ATF_TP_ADD_TCS_PTRACE_WAIT_BYTETRANSFER();
248	ATF_TP_ADD_TCS_PTRACE_WAIT_CLONE();
249	ATF_TP_ADD_TCS_PTRACE_WAIT_FORK();
250	ATF_TP_ADD_TCS_PTRACE_WAIT_SIGNAL();
251	ATF_TP_ADD_TCS_PTRACE_WAIT_EVENTMASK();
252	ATF_TP_ADD_TCS_PTRACE_WAIT_LWP();
253	ATF_TP_ADD_TCS_PTRACE_WAIT_EXEC();
254	ATF_TP_ADD_TCS_PTRACE_WAIT_TOPOLOGY();
255	ATF_TP_ADD_TCS_PTRACE_WAIT_THREADS();
256	ATF_TP_ADD_TCS_PTRACE_WAIT_SIGINFO();
257	ATF_TP_ADD_TCS_PTRACE_WAIT_CORE();
258
259	ATF_TP_ADD_TCS_PTRACE_WAIT_AMD64();
260	ATF_TP_ADD_TCS_PTRACE_WAIT_I386();
261	ATF_TP_ADD_TCS_PTRACE_WAIT_X86();
262
263#else
264	ATF_TP_ADD_TC(tp, dummy);
265#endif
266
267	return atf_no_error();
268}
269