Home | History | Annotate | Line # | Download | only in sys
t_ptrace_i386_wait.h revision 1.2.4.1
      1 /*	$NetBSD: t_ptrace_i386_wait.h,v 1.2.4.1 2019/06/10 22:10:05 christos 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