xref: /netbsd-src/tests/lib/libc/sys/t_ptrace_i386_wait.h (revision 7330f729ccf0bd976a06f95fad452fe774fc7fd1)
1 /*	$NetBSD: t_ptrace_i386_wait.h,v 1.9 2019/06/04 12:17:05 mgorny Exp $	*/
2 
3 /*-
4  * Copyright (c) 2016, 2017, 2018, 2019 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 #if defined(__i386__)
30 ATF_TC(i386_regs1);
31 ATF_TC_HEAD(i386_regs1, tc)
32 {
33 	atf_tc_set_md_var(tc, "descr",
34 	    "Call PT_GETREGS and iterate over General Purpose registers");
35 }
36 
37 ATF_TC_BODY(i386_regs1, tc)
38 {
39 	const int exitval = 5;
40 	const int sigval = SIGSTOP;
41 	pid_t child, wpid;
42 #if defined(TWAIT_HAVE_STATUS)
43 	int status;
44 #endif
45 	struct reg r;
46 
47 	DPRINTF("Before forking process PID=%d\n", getpid());
48 	SYSCALL_REQUIRE((child = fork()) != -1);
49 	if (child == 0) {
50 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
51 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
52 
53 		DPRINTF("Before raising %s from child\n", strsignal(sigval));
54 		FORKEE_ASSERT(raise(sigval) == 0);
55 
56 		DPRINTF("Before exiting of the child process\n");
57 		_exit(exitval);
58 	}
59 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
60 
61 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
62 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
63 
64 	validate_status_stopped(status, sigval);
65 
66 	DPRINTF("Call GETREGS for the child process\n");
67 	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &r, 0) != -1);
68 
69 	DPRINTF("EAX=%#" PRIxREGISTER "\n", r.r_eax);
70 	DPRINTF("EBX=%#" PRIxREGISTER "\n", r.r_ebx);
71 	DPRINTF("ECX=%#" PRIxREGISTER "\n", r.r_ecx);
72 	DPRINTF("EDX=%#" PRIxREGISTER "\n", r.r_edx);
73 
74 	DPRINTF("ESP=%#" PRIxREGISTER "\n", r.r_esp);
75 	DPRINTF("EBP=%#" PRIxREGISTER "\n", r.r_ebp);
76 
77 	DPRINTF("ESI=%#" PRIxREGISTER "\n", r.r_esi);
78 	DPRINTF("EDI=%#" PRIxREGISTER "\n", r.r_edi);
79 
80 	DPRINTF("EIP=%#" PRIxREGISTER "\n", r.r_eip);
81 
82 	DPRINTF("EFLAGS=%#" PRIxREGISTER "\n", r.r_eflags);
83 
84 	DPRINTF("CS=%#" PRIxREGISTER "\n", r.r_cs);
85 	DPRINTF("SS=%#" PRIxREGISTER "\n", r.r_ss);
86 	DPRINTF("DS=%#" PRIxREGISTER "\n", r.r_ds);
87 	DPRINTF("ES=%#" PRIxREGISTER "\n", r.r_es);
88 	DPRINTF("FS=%#" PRIxREGISTER "\n", r.r_fs);
89 	DPRINTF("GS=%#" PRIxREGISTER "\n", r.r_gs);
90 
91 	DPRINTF("Before resuming the child process where it left off and "
92 	    "without signal to be sent\n");
93 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
94 
95 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
96 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
97 
98 	validate_status_exited(status, exitval);
99 
100 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
101 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
102 }
103 
104 ATF_TC(i386_regs_gp_read);
105 ATF_TC_HEAD(i386_regs_gp_read, tc)
106 {
107 	atf_tc_set_md_var(tc, "descr",
108 		"Set general-purpose reg values from debugged program and read "
109 		"them via PT_GETREGS, comparing values against expected.");
110 }
111 
112 ATF_TC_BODY(i386_regs_gp_read, tc)
113 {
114 	const int exitval = 5;
115 	pid_t child, wpid;
116 #if defined(TWAIT_HAVE_STATUS)
117 	const int sigval = SIGTRAP;
118 	int status;
119 #endif
120 	struct reg gpr;
121 
122 	const uint32_t eax = 0x00010203;
123 	const uint32_t ebx = 0x10111213;
124 	const uint32_t ecx = 0x20212223;
125 	const uint32_t edx = 0x30313233;
126 	const uint32_t esi = 0x40414243;
127 	const uint32_t edi = 0x50515253;
128 
129 	DPRINTF("Before forking process PID=%d\n", getpid());
130 	SYSCALL_REQUIRE((child = fork()) != -1);
131 	if (child == 0) {
132 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
133 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
134 
135 		DPRINTF("Before running assembly from child\n");
136 
137 		__asm__ __volatile__(
138 			"int3\n\t"
139 			:
140 			: "a"(eax), "b"(ebx), "c"(ecx), "d"(edx), "S"(esi), "D"(edi)
141 			:
142 		);
143 
144 		DPRINTF("Before exiting of the child process\n");
145 		_exit(exitval);
146 	}
147 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
148 
149 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
150 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
151 
152 	validate_status_stopped(status, sigval);
153 
154 	DPRINTF("Call GETREGS for the child process\n");
155 	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
156 
157 	ATF_CHECK_EQ((uint32_t)gpr.r_eax, eax);
158 	ATF_CHECK_EQ((uint32_t)gpr.r_ebx, ebx);
159 	ATF_CHECK_EQ((uint32_t)gpr.r_ecx, ecx);
160 	ATF_CHECK_EQ((uint32_t)gpr.r_edx, edx);
161 	ATF_CHECK_EQ((uint32_t)gpr.r_esi, esi);
162 	ATF_CHECK_EQ((uint32_t)gpr.r_edi, edi);
163 
164 	DPRINTF("Before resuming the child process where it left off and "
165 	    "without signal to be sent\n");
166 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
167 
168 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
169 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
170 
171 	validate_status_exited(status, exitval);
172 
173 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
174 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
175 }
176 
177 ATF_TC(i386_regs_gp_write);
178 ATF_TC_HEAD(i386_regs_gp_write, tc)
179 {
180 	atf_tc_set_md_var(tc, "descr",
181 		"Set general-purpose reg values into a debugged program via "
182 		"PT_SETREGS and compare the result against expected.");
183 }
184 
185 ATF_TC_BODY(i386_regs_gp_write, tc)
186 {
187 	const int exitval = 5;
188 	pid_t child, wpid;
189 #if defined(TWAIT_HAVE_STATUS)
190 	const int sigval = SIGTRAP;
191 	int status;
192 #endif
193 	struct reg gpr;
194 
195 	const uint32_t eax = 0x00010203;
196 	const uint32_t ebx = 0x10111213;
197 	const uint32_t ecx = 0x20212223;
198 	const uint32_t edx = 0x30313233;
199 	const uint32_t esi = 0x40414243;
200 	const uint32_t edi = 0x50515253;
201 
202 	DPRINTF("Before forking process PID=%d\n", getpid());
203 	SYSCALL_REQUIRE((child = fork()) != -1);
204 	if (child == 0) {
205 		const uint64_t fill = 0x0F0F0F0F;
206 		uint32_t v_eax, v_ebx, v_ecx, v_edx, v_esi, v_edi;
207 
208 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
209 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
210 
211 		DPRINTF("Before running assembly from child\n");
212 
213 		__asm__ __volatile__(
214 			/* fill registers with clobber pattern */
215 			"movl    %6, %%eax\n\t"
216 			"movl    %6, %%ebx\n\t"
217 			"movl    %6, %%ecx\n\t"
218 			"movl    %6, %%edx\n\t"
219 			"movl    %6, %%esi\n\t"
220 			"movl    %6, %%edi\n\t"
221 			"\n\t"
222 			"int3\n\t"
223 			: "=a"(v_eax), "=b"(v_ebx), "=c"(v_ecx), "=d"(v_edx), "=S"(v_esi),
224 			"=D"(v_edi)
225 			: "g"(fill)
226 			:
227 		);
228 
229 		DPRINTF("Before comparing results\n");
230 		FORKEE_ASSERT_EQ(v_eax, eax);
231 		FORKEE_ASSERT_EQ(v_ebx, ebx);
232 		FORKEE_ASSERT_EQ(v_ecx, ecx);
233 		FORKEE_ASSERT_EQ(v_edx, edx);
234 		FORKEE_ASSERT_EQ(v_esi, esi);
235 		FORKEE_ASSERT_EQ(v_edi, edi);
236 
237 		DPRINTF("Before exiting of the child process\n");
238 		_exit(exitval);
239 	}
240 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
241 
242 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
243 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
244 
245 	validate_status_stopped(status, sigval);
246 
247 	DPRINTF("Call GETREGS for the child process\n");
248 	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
249 
250 	gpr.r_eax = eax;
251 	gpr.r_ebx = ebx;
252 	gpr.r_ecx = ecx;
253 	gpr.r_edx = edx;
254 	gpr.r_esi = esi;
255 	gpr.r_edi = edi;
256 
257 	DPRINTF("Call SETREGS for the child process\n");
258 	SYSCALL_REQUIRE(ptrace(PT_SETREGS, child, &gpr, 0) != -1);
259 
260 	DPRINTF("Before resuming the child process where it left off and "
261 	    "without signal to be sent\n");
262 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
263 
264 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
265 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
266 
267 	validate_status_exited(status, exitval);
268 
269 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
270 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
271 }
272 
273 ATF_TC(i386_regs_ebp_esp_read);
274 ATF_TC_HEAD(i386_regs_ebp_esp_read, tc)
275 {
276 	atf_tc_set_md_var(tc, "descr",
277 		"Set EBP & ESP reg values from debugged program and read "
278 		"them via PT_GETREGS, comparing values against expected.");
279 }
280 
281 ATF_TC_BODY(i386_regs_ebp_esp_read, tc)
282 {
283 	const int exitval = 5;
284 	pid_t child, wpid;
285 #if defined(TWAIT_HAVE_STATUS)
286 	const int sigval = SIGTRAP;
287 	int status;
288 #endif
289 	struct reg gpr;
290 
291 	const uint32_t esp = 0x60616263;
292 	const uint32_t ebp = 0x70717273;
293 
294 	DPRINTF("Before forking process PID=%d\n", getpid());
295 	SYSCALL_REQUIRE((child = fork()) != -1);
296 	if (child == 0) {
297 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
298 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
299 
300 		DPRINTF("Before running assembly from child\n");
301 
302 		__asm__ __volatile__(
303 			/* ebp & ebp are a bit tricky, we must not clobber them */
304 			"movl    %%esp, %%eax\n\t"
305 			"movl    %%ebp, %%ebx\n\t"
306 			"movl    %0, %%esp\n\t"
307 			"movl    %1, %%ebp\n\t"
308 			"\n\t"
309 			"int3\n\t"
310 			"\n\t"
311 			"movl    %%eax, %%esp\n\t"
312 			"movl    %%ebx, %%ebp\n\t"
313 			:
314 			: "ri"(esp), "ri"(ebp)
315 			: "%eax", "%ebx"
316 		);
317 
318 		DPRINTF("Before exiting of the child process\n");
319 		_exit(exitval);
320 	}
321 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
322 
323 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
324 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
325 
326 	validate_status_stopped(status, sigval);
327 
328 	DPRINTF("Call GETREGS for the child process\n");
329 	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
330 
331 	ATF_CHECK_EQ((uint32_t)gpr.r_esp, esp);
332 	ATF_CHECK_EQ((uint32_t)gpr.r_ebp, ebp);
333 
334 	DPRINTF("Before resuming the child process where it left off and "
335 	    "without signal to be sent\n");
336 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
337 
338 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
339 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
340 
341 	validate_status_exited(status, exitval);
342 
343 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
344 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
345 }
346 
347 ATF_TC(i386_regs_ebp_esp_write);
348 ATF_TC_HEAD(i386_regs_ebp_esp_write, tc)
349 {
350 	atf_tc_set_md_var(tc, "descr",
351 		"Set EBP & ESP reg values into a debugged program via "
352 		"PT_SETREGS and compare the result against expected.");
353 }
354 
355 ATF_TC_BODY(i386_regs_ebp_esp_write, tc)
356 {
357 	const int exitval = 5;
358 	pid_t child, wpid;
359 #if defined(TWAIT_HAVE_STATUS)
360 	const int sigval = SIGTRAP;
361 	int status;
362 #endif
363 	struct reg gpr;
364 
365 	const uint32_t esp = 0x60616263;
366 	const uint32_t ebp = 0x70717273;
367 
368 	DPRINTF("Before forking process PID=%d\n", getpid());
369 	SYSCALL_REQUIRE((child = fork()) != -1);
370 	if (child == 0) {
371 		const uint64_t fill = 0x0F0F0F0F;
372 		uint32_t v_esp, v_ebp;
373 
374 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
375 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
376 
377 		DPRINTF("Before running assembly from child\n");
378 
379 		__asm__ __volatile__(
380 			/* save original ebp & esp using our output registers */
381 			"movl    %%esp, %0\n\t"
382 			"movl    %%ebp, %1\n\t"
383 			/* fill them with clobber pattern */
384 			"movl    %2, %%esp\n\t"
385 			"movl    %2, %%ebp\n\t"
386 			"\n\t"
387 			"int3\n\t"
388 			"\n\t"
389 			/* restore ebp & esp, and save the result */
390 			"xchgl   %%esp, %0\n\t"
391 			"xchgl   %%ebp, %1\n\t"
392 			: "=r"(v_esp), "=r"(v_ebp)
393 			: "g"(fill)
394 			:
395 		);
396 
397 		DPRINTF("Before comparing results\n");
398 		FORKEE_ASSERT_EQ(v_esp, esp);
399 		FORKEE_ASSERT_EQ(v_ebp, ebp);
400 
401 		DPRINTF("Before exiting of the child process\n");
402 		_exit(exitval);
403 	}
404 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
405 
406 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
407 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
408 
409 	validate_status_stopped(status, sigval);
410 
411 	DPRINTF("Call GETREGS for the child process\n");
412 	SYSCALL_REQUIRE(ptrace(PT_GETREGS, child, &gpr, 0) != -1);
413 
414 	gpr.r_esp = esp;
415 	gpr.r_ebp = ebp;
416 
417 	DPRINTF("Call SETREGS for the child process\n");
418 	SYSCALL_REQUIRE(ptrace(PT_SETREGS, child, &gpr, 0) != -1);
419 
420 	DPRINTF("Before resuming the child process where it left off and "
421 	    "without signal to be sent\n");
422 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
423 
424 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
425 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
426 
427 	validate_status_exited(status, exitval);
428 
429 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
430 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
431 }
432 
433 #define ATF_TP_ADD_TCS_PTRACE_WAIT_I386() \
434 	ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs1); \
435 	ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs_gp_read); \
436 	ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs_gp_write); \
437 	ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs_ebp_esp_read); \
438 	ATF_TP_ADD_TC_HAVE_GPREGS(tp, i386_regs_ebp_esp_write);
439 #else
440 #define ATF_TP_ADD_TCS_PTRACE_WAIT_I386()
441 #endif
442