Home | History | Annotate | Line # | Download | only in sys
t_ptrace_bytetransfer_wait.h revision 1.1
      1 /*	$NetBSD: t_ptrace_bytetransfer_wait.h,v 1.1 2020/05/04 22:05:28 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 
     30 enum bytes_transfer_type {
     31 	BYTES_TRANSFER_DATA,
     32 	BYTES_TRANSFER_DATAIO,
     33 	BYTES_TRANSFER_TEXT,
     34 	BYTES_TRANSFER_TEXTIO,
     35 	BYTES_TRANSFER_AUXV
     36 };
     37 
     38 static int __used
     39 bytes_transfer_dummy(int a, int b, int c, int d)
     40 {
     41 	int e, f, g, h;
     42 
     43 	a *= 4;
     44 	b += 3;
     45 	c -= 2;
     46 	d /= 1;
     47 
     48 	e = strtol("10", NULL, 10);
     49 	f = strtol("20", NULL, 10);
     50 	g = strtol("30", NULL, 10);
     51 	h = strtol("40", NULL, 10);
     52 
     53 	return (a + b * c - d) + (e * f - g / h);
     54 }
     55 
     56 static void
     57 bytes_transfer(int operation, size_t size, enum bytes_transfer_type type)
     58 {
     59 	const int exitval = 5;
     60 	const int sigval = SIGSTOP;
     61 	pid_t child, wpid;
     62 	bool skip = false;
     63 
     64 	int lookup_me = 0;
     65 	uint8_t lookup_me8 = 0;
     66 	uint16_t lookup_me16 = 0;
     67 	uint32_t lookup_me32 = 0;
     68 	uint64_t lookup_me64 = 0;
     69 
     70 	int magic = 0x13579246;
     71 	uint8_t magic8 = 0xab;
     72 	uint16_t magic16 = 0x1234;
     73 	uint32_t magic32 = 0x98765432;
     74 	uint64_t magic64 = 0xabcdef0123456789;
     75 
     76 	struct ptrace_io_desc io;
     77 #if defined(TWAIT_HAVE_STATUS)
     78 	int status;
     79 #endif
     80 	/* 513 is just enough, for the purposes of ATF it's good enough */
     81 	AuxInfo ai[513], *aip;
     82 
     83 	ATF_REQUIRE(size < sizeof(ai));
     84 
     85 	/* Prepare variables for .TEXT transfers */
     86 	switch (type) {
     87 	case BYTES_TRANSFER_TEXT:
     88 		memcpy(&magic, bytes_transfer_dummy, sizeof(magic));
     89 		break;
     90 	case BYTES_TRANSFER_TEXTIO:
     91 		switch (size) {
     92 		case 8:
     93 			memcpy(&magic8, bytes_transfer_dummy, sizeof(magic8));
     94 			break;
     95 		case 16:
     96 			memcpy(&magic16, bytes_transfer_dummy, sizeof(magic16));
     97 			break;
     98 		case 32:
     99 			memcpy(&magic32, bytes_transfer_dummy, sizeof(magic32));
    100 			break;
    101 		case 64:
    102 			memcpy(&magic64, bytes_transfer_dummy, sizeof(magic64));
    103 			break;
    104 		}
    105 		break;
    106 	default:
    107 		break;
    108 	}
    109 
    110 	/* Prepare variables for PIOD and AUXV transfers */
    111 	switch (type) {
    112 	case BYTES_TRANSFER_TEXTIO:
    113 	case BYTES_TRANSFER_DATAIO:
    114 		io.piod_op = operation;
    115 		switch (size) {
    116 		case 8:
    117 			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
    118 			               (void *)bytes_transfer_dummy :
    119 			               &lookup_me8;
    120 			io.piod_addr = &lookup_me8;
    121 			io.piod_len = sizeof(lookup_me8);
    122 			break;
    123 		case 16:
    124 			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
    125 			               (void *)bytes_transfer_dummy :
    126 			               &lookup_me16;
    127 			io.piod_addr = &lookup_me16;
    128 			io.piod_len = sizeof(lookup_me16);
    129 			break;
    130 		case 32:
    131 			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
    132 			               (void *)bytes_transfer_dummy :
    133 			               &lookup_me32;
    134 			io.piod_addr = &lookup_me32;
    135 			io.piod_len = sizeof(lookup_me32);
    136 			break;
    137 		case 64:
    138 			io.piod_offs = (type == BYTES_TRANSFER_TEXTIO) ?
    139 			               (void *)bytes_transfer_dummy :
    140 			               &lookup_me64;
    141 			io.piod_addr = &lookup_me64;
    142 			io.piod_len = sizeof(lookup_me64);
    143 			break;
    144 		default:
    145 			break;
    146 		}
    147 		break;
    148 	case BYTES_TRANSFER_AUXV:
    149 		io.piod_op = operation;
    150 		io.piod_offs = 0;
    151 		io.piod_addr = ai;
    152 		io.piod_len = size;
    153 		break;
    154 	default:
    155 		break;
    156 	}
    157 
    158 	DPRINTF("Before forking process PID=%d\n", getpid());
    159 	SYSCALL_REQUIRE((child = fork()) != -1);
    160 	if (child == 0) {
    161 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
    162 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
    163 
    164 		switch (type) {
    165 		case BYTES_TRANSFER_DATA:
    166 			switch (operation) {
    167 			case PT_READ_D:
    168 			case PT_READ_I:
    169 				lookup_me = magic;
    170 				break;
    171 			default:
    172 				break;
    173 			}
    174 			break;
    175 		case BYTES_TRANSFER_DATAIO:
    176 			switch (operation) {
    177 			case PIOD_READ_D:
    178 			case PIOD_READ_I:
    179 				switch (size) {
    180 				case 8:
    181 					lookup_me8 = magic8;
    182 					break;
    183 				case 16:
    184 					lookup_me16 = magic16;
    185 					break;
    186 				case 32:
    187 					lookup_me32 = magic32;
    188 					break;
    189 				case 64:
    190 					lookup_me64 = magic64;
    191 					break;
    192 				default:
    193 					break;
    194 				}
    195 				break;
    196 			default:
    197 				break;
    198 			}
    199 		default:
    200 			break;
    201 		}
    202 
    203 		DPRINTF("Before raising %s from child\n", strsignal(sigval));
    204 		FORKEE_ASSERT(raise(sigval) == 0);
    205 
    206 		/* Handle PIOD and PT separately as operation values overlap */
    207 		switch (type) {
    208 		case BYTES_TRANSFER_DATA:
    209 			switch (operation) {
    210 			case PT_WRITE_D:
    211 			case PT_WRITE_I:
    212 				FORKEE_ASSERT_EQ(lookup_me, magic);
    213 				break;
    214 			default:
    215 				break;
    216 			}
    217 			break;
    218 		case BYTES_TRANSFER_DATAIO:
    219 			switch (operation) {
    220 			case PIOD_WRITE_D:
    221 			case PIOD_WRITE_I:
    222 				switch (size) {
    223 				case 8:
    224 					FORKEE_ASSERT_EQ(lookup_me8, magic8);
    225 					break;
    226 				case 16:
    227 					FORKEE_ASSERT_EQ(lookup_me16, magic16);
    228 					break;
    229 				case 32:
    230 					FORKEE_ASSERT_EQ(lookup_me32, magic32);
    231 					break;
    232 				case 64:
    233 					FORKEE_ASSERT_EQ(lookup_me64, magic64);
    234 					break;
    235 				default:
    236 					break;
    237 				}
    238 				break;
    239 			default:
    240 				break;
    241 			}
    242 			break;
    243 		case BYTES_TRANSFER_TEXT:
    244 			FORKEE_ASSERT(memcmp(&magic, bytes_transfer_dummy,
    245 			                     sizeof(magic)) == 0);
    246 			break;
    247 		case BYTES_TRANSFER_TEXTIO:
    248 			switch (size) {
    249 			case 8:
    250 				FORKEE_ASSERT(memcmp(&magic8,
    251 				                     bytes_transfer_dummy,
    252 				                     sizeof(magic8)) == 0);
    253 				break;
    254 			case 16:
    255 				FORKEE_ASSERT(memcmp(&magic16,
    256 				                     bytes_transfer_dummy,
    257 				                     sizeof(magic16)) == 0);
    258 				break;
    259 			case 32:
    260 				FORKEE_ASSERT(memcmp(&magic32,
    261 				                     bytes_transfer_dummy,
    262 				                     sizeof(magic32)) == 0);
    263 				break;
    264 			case 64:
    265 				FORKEE_ASSERT(memcmp(&magic64,
    266 				                     bytes_transfer_dummy,
    267 				                     sizeof(magic64)) == 0);
    268 				break;
    269 			}
    270 			break;
    271 		default:
    272 			break;
    273 		}
    274 
    275 		DPRINTF("Before exiting of the child process\n");
    276 		_exit(exitval);
    277 	}
    278 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
    279 
    280 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
    281 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
    282 
    283 	validate_status_stopped(status, sigval);
    284 
    285 	/* Check PaX MPROTECT */
    286 	if (!can_we_write_to_text(child)) {
    287 		switch (type) {
    288 		case BYTES_TRANSFER_TEXTIO:
    289 			switch (operation) {
    290 			case PIOD_WRITE_D:
    291 			case PIOD_WRITE_I:
    292 				skip = true;
    293 				break;
    294 			default:
    295 				break;
    296 			}
    297 			break;
    298 		case BYTES_TRANSFER_TEXT:
    299 			switch (operation) {
    300 			case PT_WRITE_D:
    301 			case PT_WRITE_I:
    302 				skip = true;
    303 				break;
    304 			default:
    305 				break;
    306 			}
    307 			break;
    308 		default:
    309 			break;
    310 		}
    311 	}
    312 
    313 	/* Bailout cleanly killing the child process */
    314 	if (skip) {
    315 		SYSCALL_REQUIRE(ptrace(PT_KILL, child, (void *)1, 0) != -1);
    316 		DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
    317 		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
    318 		                      child);
    319 
    320 		validate_status_signaled(status, SIGKILL, 0);
    321 
    322 		atf_tc_skip("PaX MPROTECT setup prevents writes to .text");
    323 	}
    324 
    325 	DPRINTF("Calling operation to transfer bytes between child=%d and "
    326 	       "parent=%d\n", child, getpid());
    327 
    328 	switch (type) {
    329 	case BYTES_TRANSFER_TEXTIO:
    330 	case BYTES_TRANSFER_DATAIO:
    331 	case BYTES_TRANSFER_AUXV:
    332 		switch (operation) {
    333 		case PIOD_WRITE_D:
    334 		case PIOD_WRITE_I:
    335 			switch (size) {
    336 			case 8:
    337 				lookup_me8 = magic8;
    338 				break;
    339 			case 16:
    340 				lookup_me16 = magic16;
    341 				break;
    342 			case 32:
    343 				lookup_me32 = magic32;
    344 				break;
    345 			case 64:
    346 				lookup_me64 = magic64;
    347 				break;
    348 			default:
    349 				break;
    350 			}
    351 			break;
    352 		default:
    353 			break;
    354 		}
    355 		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, 0) != -1);
    356 		switch (operation) {
    357 		case PIOD_READ_D:
    358 		case PIOD_READ_I:
    359 			switch (size) {
    360 			case 8:
    361 				ATF_REQUIRE_EQ(lookup_me8, magic8);
    362 				break;
    363 			case 16:
    364 				ATF_REQUIRE_EQ(lookup_me16, magic16);
    365 				break;
    366 			case 32:
    367 				ATF_REQUIRE_EQ(lookup_me32, magic32);
    368 				break;
    369 			case 64:
    370 				ATF_REQUIRE_EQ(lookup_me64, magic64);
    371 				break;
    372 			default:
    373 				break;
    374 			}
    375 			break;
    376 		case PIOD_READ_AUXV:
    377 			DPRINTF("Asserting that AUXV length (%zu) is > 0\n",
    378 			        io.piod_len);
    379 			ATF_REQUIRE(io.piod_len > 0);
    380 			for (aip = ai; aip->a_type != AT_NULL; aip++)
    381 				DPRINTF("a_type=%#llx a_v=%#llx\n",
    382 				    (long long int)aip->a_type,
    383 				    (long long int)aip->a_v);
    384 			break;
    385 		default:
    386 			break;
    387 		}
    388 		break;
    389 	case BYTES_TRANSFER_TEXT:
    390 		switch (operation) {
    391 		case PT_READ_D:
    392 		case PT_READ_I:
    393 			errno = 0;
    394 			lookup_me = ptrace(operation, child,
    395 			                   bytes_transfer_dummy, 0);
    396 			ATF_REQUIRE_EQ(lookup_me, magic);
    397 			SYSCALL_REQUIRE_ERRNO(errno, 0);
    398 			break;
    399 		case PT_WRITE_D:
    400 		case PT_WRITE_I:
    401 			SYSCALL_REQUIRE(ptrace(operation, child,
    402 			                       bytes_transfer_dummy, magic)
    403 			                != -1);
    404 			break;
    405 		default:
    406 			break;
    407 		}
    408 		break;
    409 	case BYTES_TRANSFER_DATA:
    410 		switch (operation) {
    411 		case PT_READ_D:
    412 		case PT_READ_I:
    413 			errno = 0;
    414 			lookup_me = ptrace(operation, child, &lookup_me, 0);
    415 			ATF_REQUIRE_EQ(lookup_me, magic);
    416 			SYSCALL_REQUIRE_ERRNO(errno, 0);
    417 			break;
    418 		case PT_WRITE_D:
    419 		case PT_WRITE_I:
    420 			lookup_me = magic;
    421 			SYSCALL_REQUIRE(ptrace(operation, child, &lookup_me,
    422 			                       magic) != -1);
    423 			break;
    424 		default:
    425 			break;
    426 		}
    427 		break;
    428 	default:
    429 		break;
    430 	}
    431 
    432 	DPRINTF("Before resuming the child process where it left off and "
    433 	    "without signal to be sent\n");
    434 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
    435 
    436 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
    437 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
    438 
    439 	validate_status_exited(status, exitval);
    440 
    441 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
    442 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
    443 }
    444 
    445 #define BYTES_TRANSFER(test, operation, size, type)			\
    446 ATF_TC(test);								\
    447 ATF_TC_HEAD(test, tc)							\
    448 {									\
    449 	atf_tc_set_md_var(tc, "descr",					\
    450 	    "Verify bytes transfer operation" #operation " and size " #size \
    451 	    " of type " #type);						\
    452 }									\
    453 									\
    454 ATF_TC_BODY(test, tc)							\
    455 {									\
    456 									\
    457 	bytes_transfer(operation, size, BYTES_TRANSFER_##type);		\
    458 }
    459 
    460 // DATA
    461 
    462 BYTES_TRANSFER(bytes_transfer_piod_read_d_8, PIOD_READ_D, 8, DATAIO)
    463 BYTES_TRANSFER(bytes_transfer_piod_read_d_16, PIOD_READ_D, 16, DATAIO)
    464 BYTES_TRANSFER(bytes_transfer_piod_read_d_32, PIOD_READ_D, 32, DATAIO)
    465 BYTES_TRANSFER(bytes_transfer_piod_read_d_64, PIOD_READ_D, 64, DATAIO)
    466 
    467 BYTES_TRANSFER(bytes_transfer_piod_read_i_8, PIOD_READ_I, 8, DATAIO)
    468 BYTES_TRANSFER(bytes_transfer_piod_read_i_16, PIOD_READ_I, 16, DATAIO)
    469 BYTES_TRANSFER(bytes_transfer_piod_read_i_32, PIOD_READ_I, 32, DATAIO)
    470 BYTES_TRANSFER(bytes_transfer_piod_read_i_64, PIOD_READ_I, 64, DATAIO)
    471 
    472 BYTES_TRANSFER(bytes_transfer_piod_write_d_8, PIOD_WRITE_D, 8, DATAIO)
    473 BYTES_TRANSFER(bytes_transfer_piod_write_d_16, PIOD_WRITE_D, 16, DATAIO)
    474 BYTES_TRANSFER(bytes_transfer_piod_write_d_32, PIOD_WRITE_D, 32, DATAIO)
    475 BYTES_TRANSFER(bytes_transfer_piod_write_d_64, PIOD_WRITE_D, 64, DATAIO)
    476 
    477 BYTES_TRANSFER(bytes_transfer_piod_write_i_8, PIOD_WRITE_I, 8, DATAIO)
    478 BYTES_TRANSFER(bytes_transfer_piod_write_i_16, PIOD_WRITE_I, 16, DATAIO)
    479 BYTES_TRANSFER(bytes_transfer_piod_write_i_32, PIOD_WRITE_I, 32, DATAIO)
    480 BYTES_TRANSFER(bytes_transfer_piod_write_i_64, PIOD_WRITE_I, 64, DATAIO)
    481 
    482 BYTES_TRANSFER(bytes_transfer_read_d, PT_READ_D, 32, DATA)
    483 BYTES_TRANSFER(bytes_transfer_read_i, PT_READ_I, 32, DATA)
    484 BYTES_TRANSFER(bytes_transfer_write_d, PT_WRITE_D, 32, DATA)
    485 BYTES_TRANSFER(bytes_transfer_write_i, PT_WRITE_I, 32, DATA)
    486 
    487 // TEXT
    488 
    489 BYTES_TRANSFER(bytes_transfer_piod_read_d_8_text, PIOD_READ_D, 8, TEXTIO)
    490 BYTES_TRANSFER(bytes_transfer_piod_read_d_16_text, PIOD_READ_D, 16, TEXTIO)
    491 BYTES_TRANSFER(bytes_transfer_piod_read_d_32_text, PIOD_READ_D, 32, TEXTIO)
    492 BYTES_TRANSFER(bytes_transfer_piod_read_d_64_text, PIOD_READ_D, 64, TEXTIO)
    493 
    494 BYTES_TRANSFER(bytes_transfer_piod_read_i_8_text, PIOD_READ_I, 8, TEXTIO)
    495 BYTES_TRANSFER(bytes_transfer_piod_read_i_16_text, PIOD_READ_I, 16, TEXTIO)
    496 BYTES_TRANSFER(bytes_transfer_piod_read_i_32_text, PIOD_READ_I, 32, TEXTIO)
    497 BYTES_TRANSFER(bytes_transfer_piod_read_i_64_text, PIOD_READ_I, 64, TEXTIO)
    498 
    499 BYTES_TRANSFER(bytes_transfer_piod_write_d_8_text, PIOD_WRITE_D, 8, TEXTIO)
    500 BYTES_TRANSFER(bytes_transfer_piod_write_d_16_text, PIOD_WRITE_D, 16, TEXTIO)
    501 BYTES_TRANSFER(bytes_transfer_piod_write_d_32_text, PIOD_WRITE_D, 32, TEXTIO)
    502 BYTES_TRANSFER(bytes_transfer_piod_write_d_64_text, PIOD_WRITE_D, 64, TEXTIO)
    503 
    504 BYTES_TRANSFER(bytes_transfer_piod_write_i_8_text, PIOD_WRITE_I, 8, TEXTIO)
    505 BYTES_TRANSFER(bytes_transfer_piod_write_i_16_text, PIOD_WRITE_I, 16, TEXTIO)
    506 BYTES_TRANSFER(bytes_transfer_piod_write_i_32_text, PIOD_WRITE_I, 32, TEXTIO)
    507 BYTES_TRANSFER(bytes_transfer_piod_write_i_64_text, PIOD_WRITE_I, 64, TEXTIO)
    508 
    509 BYTES_TRANSFER(bytes_transfer_read_d_text, PT_READ_D, 32, TEXT)
    510 BYTES_TRANSFER(bytes_transfer_read_i_text, PT_READ_I, 32, TEXT)
    511 BYTES_TRANSFER(bytes_transfer_write_d_text, PT_WRITE_D, 32, TEXT)
    512 BYTES_TRANSFER(bytes_transfer_write_i_text, PT_WRITE_I, 32, TEXT)
    513 
    514 // AUXV
    515 
    516 BYTES_TRANSFER(bytes_transfer_piod_read_auxv, PIOD_READ_AUXV, 4096, AUXV)
    517 
    518 /// ----------------------------------------------------------------------------
    519 
    520 static void
    521 bytes_transfer_alignment(const char *operation)
    522 {
    523 	const int exitval = 5;
    524 	const int sigval = SIGSTOP;
    525 	pid_t child, wpid;
    526 #if defined(TWAIT_HAVE_STATUS)
    527 	int status;
    528 #endif
    529 	char *buffer;
    530 	int vector;
    531 	size_t len;
    532 	size_t i;
    533 	int op;
    534 
    535 	struct ptrace_io_desc io;
    536 	struct ptrace_siginfo info;
    537 
    538 	memset(&io, 0, sizeof(io));
    539 	memset(&info, 0, sizeof(info));
    540 
    541 	/* Testing misaligned byte transfer crossing page boundaries */
    542 	len = sysconf(_SC_PAGESIZE) * 2;
    543 	buffer = malloc(len);
    544 	ATF_REQUIRE(buffer != NULL);
    545 
    546 	/* Initialize the buffer with random data */
    547 	for (i = 0; i < len; i++)
    548 		buffer[i] = i & 0xff;
    549 
    550 	DPRINTF("Before forking process PID=%d\n", getpid());
    551 	SYSCALL_REQUIRE((child = fork()) != -1);
    552 	if (child == 0) {
    553 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
    554 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
    555 
    556 		DPRINTF("Before raising %s from child\n", strsignal(sigval));
    557 		FORKEE_ASSERT(raise(sigval) == 0);
    558 
    559 		DPRINTF("Before exiting of the child process\n");
    560 		_exit(exitval);
    561 	}
    562 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
    563 
    564 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
    565 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
    566 
    567 	validate_status_stopped(status, sigval);
    568 
    569 	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
    570 	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
    571 		!= -1);
    572 
    573 	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
    574 	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
    575 		"si_errno=%#x\n",
    576 		info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
    577 		info.psi_siginfo.si_errno);
    578 
    579 	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
    580 	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
    581 
    582 	if (strcmp(operation, "PT_READ_I") == 0 ||
    583 	    strcmp(operation, "PT_READ_D") == 0) {
    584 		if (strcmp(operation, "PT_READ_I"))
    585 			op = PT_READ_I;
    586 		else
    587 			op = PT_READ_D;
    588 
    589 		for (i = 0; i <= (len - sizeof(int)); i++) {
    590 			errno = 0;
    591 			vector = ptrace(op, child, buffer + i, 0);
    592 			ATF_REQUIRE_EQ(errno, 0);
    593 			ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int)));
    594 		}
    595 	} else if (strcmp(operation, "PT_WRITE_I") == 0 ||
    596 	           strcmp(operation, "PT_WRITE_D") == 0) {
    597 		if (strcmp(operation, "PT_WRITE_I"))
    598 			op = PT_WRITE_I;
    599 		else
    600 			op = PT_WRITE_D;
    601 
    602 		for (i = 0; i <= (len - sizeof(int)); i++) {
    603 			memcpy(&vector, buffer + i, sizeof(int));
    604 			SYSCALL_REQUIRE(ptrace(op, child, buffer + 1, vector)
    605 			    != -1);
    606 		}
    607 	} else if (strcmp(operation, "PIOD_READ_I") == 0 ||
    608 	           strcmp(operation, "PIOD_READ_D") == 0) {
    609 		if (strcmp(operation, "PIOD_READ_I"))
    610 			op = PIOD_READ_I;
    611 		else
    612 			op = PIOD_READ_D;
    613 
    614 		io.piod_op = op;
    615 		io.piod_addr = &vector;
    616 		io.piod_len = sizeof(int);
    617 
    618 		for (i = 0; i <= (len - sizeof(int)); i++) {
    619 			io.piod_offs = buffer + i;
    620 
    621 			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
    622 			                != -1);
    623 			ATF_REQUIRE(!memcmp(&vector, buffer + i, sizeof(int)));
    624 		}
    625 	} else if (strcmp(operation, "PIOD_WRITE_I") == 0 ||
    626 	           strcmp(operation, "PIOD_WRITE_D") == 0) {
    627 		if (strcmp(operation, "PIOD_WRITE_I"))
    628 			op = PIOD_WRITE_I;
    629 		else
    630 			op = PIOD_WRITE_D;
    631 
    632 		io.piod_op = op;
    633 		io.piod_addr = &vector;
    634 		io.piod_len = sizeof(int);
    635 
    636 		for (i = 0; i <= (len - sizeof(int)); i++) {
    637 			io.piod_offs = buffer + i;
    638 
    639 			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
    640 			                != -1);
    641 		}
    642 	} else if (strcmp(operation, "PIOD_READ_AUXV") == 0) {
    643 		io.piod_op = PIOD_READ_AUXV;
    644 		io.piod_addr = &vector;
    645 		io.piod_len = sizeof(int);
    646 
    647 		errno = 0;
    648 		i = 0;
    649 		/* Read the whole AUXV vector, it has no clear length */
    650 		while (io.piod_len > 0) {
    651 			io.piod_offs = (void *)(intptr_t)i;
    652 			SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io))
    653 			                != -1 || (io.piod_len == 0 && i > 0));
    654 			++i;
    655 		}
    656 	}
    657 
    658 	DPRINTF("Before resuming the child process where it left off "
    659 	    "and without signal to be sent\n");
    660 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
    661 
    662 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
    663 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
    664 	    child);
    665 
    666 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
    667 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
    668 }
    669 
    670 #define BYTES_TRANSFER_ALIGNMENT(test, operation)			\
    671 ATF_TC(test);								\
    672 ATF_TC_HEAD(test, tc)							\
    673 {									\
    674 	atf_tc_set_md_var(tc, "descr",					\
    675 	    "Verify bytes transfer for potentially misaligned "		\
    676 	    "operation " operation);					\
    677 }									\
    678 									\
    679 ATF_TC_BODY(test, tc)							\
    680 {									\
    681 									\
    682 	bytes_transfer_alignment(operation);				\
    683 }
    684 
    685 BYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_i, "PT_READ_I")
    686 BYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_read_d, "PT_READ_D")
    687 BYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_i, "PT_WRITE_I")
    688 BYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_pt_write_d, "PT_WRITE_D")
    689 
    690 BYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_i, "PIOD_READ_I")
    691 BYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_d, "PIOD_READ_D")
    692 BYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_i, "PIOD_WRITE_I")
    693 BYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_write_d, "PIOD_WRITE_D")
    694 
    695 BYTES_TRANSFER_ALIGNMENT(bytes_transfer_alignment_piod_read_auxv, "PIOD_READ_AUXV")
    696 
    697 /// ----------------------------------------------------------------------------
    698 
    699 static void
    700 bytes_transfer_eof(const char *operation)
    701 {
    702 	const int exitval = 5;
    703 	const int sigval = SIGSTOP;
    704 	pid_t child, wpid;
    705 #if defined(TWAIT_HAVE_STATUS)
    706 	int status;
    707 #endif
    708 	FILE *fp;
    709 	char *p;
    710 	int vector;
    711 	int op;
    712 
    713 	struct ptrace_io_desc io;
    714 	struct ptrace_siginfo info;
    715 
    716 	memset(&io, 0, sizeof(io));
    717 	memset(&info, 0, sizeof(info));
    718 
    719 	vector = 0;
    720 
    721 	fp = tmpfile();
    722 	ATF_REQUIRE(fp != NULL);
    723 
    724 	p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0);
    725 	ATF_REQUIRE(p != MAP_FAILED);
    726 
    727 	DPRINTF("Before forking process PID=%d\n", getpid());
    728 	SYSCALL_REQUIRE((child = fork()) != -1);
    729 	if (child == 0) {
    730 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
    731 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
    732 
    733 		DPRINTF("Before raising %s from child\n", strsignal(sigval));
    734 		FORKEE_ASSERT(raise(sigval) == 0);
    735 
    736 		DPRINTF("Before exiting of the child process\n");
    737 		_exit(exitval);
    738 	}
    739 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
    740 
    741 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
    742 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
    743 
    744 	validate_status_stopped(status, sigval);
    745 
    746 	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
    747 	SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info))
    748 		!= -1);
    749 
    750 	DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
    751 	DPRINTF("Signal properties: si_signo=%#x si_code=%#x "
    752 		"si_errno=%#x\n",
    753 		info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
    754 		info.psi_siginfo.si_errno);
    755 
    756 	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
    757 	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
    758 
    759 	if (strcmp(operation, "PT_READ_I") == 0 ||
    760 	    strcmp(operation, "PT_READ_D") == 0) {
    761 		if (strcmp(operation, "PT_READ_I"))
    762 			op = PT_READ_I;
    763 		else
    764 			op = PT_READ_D;
    765 
    766 		errno = 0;
    767 		SYSCALL_REQUIRE(ptrace(op, child, p, 0) == -1);
    768 		ATF_REQUIRE_EQ(errno, EINVAL);
    769 	} else if (strcmp(operation, "PT_WRITE_I") == 0 ||
    770 	           strcmp(operation, "PT_WRITE_D") == 0) {
    771 		if (strcmp(operation, "PT_WRITE_I"))
    772 			op = PT_WRITE_I;
    773 		else
    774 			op = PT_WRITE_D;
    775 
    776 		errno = 0;
    777 		SYSCALL_REQUIRE(ptrace(op, child, p, vector) == -1);
    778 		ATF_REQUIRE_EQ(errno, EINVAL);
    779 	} else if (strcmp(operation, "PIOD_READ_I") == 0 ||
    780 	           strcmp(operation, "PIOD_READ_D") == 0) {
    781 		if (strcmp(operation, "PIOD_READ_I"))
    782 			op = PIOD_READ_I;
    783 		else
    784 			op = PIOD_READ_D;
    785 
    786 		io.piod_op = op;
    787 		io.piod_addr = &vector;
    788 		io.piod_len = sizeof(int);
    789 		io.piod_offs = p;
    790 
    791 		errno = 0;
    792 		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1);
    793 		ATF_REQUIRE_EQ(errno, EINVAL);
    794 	} else if (strcmp(operation, "PIOD_WRITE_I") == 0 ||
    795 	           strcmp(operation, "PIOD_WRITE_D") == 0) {
    796 		if (strcmp(operation, "PIOD_WRITE_I"))
    797 			op = PIOD_WRITE_I;
    798 		else
    799 			op = PIOD_WRITE_D;
    800 
    801 		io.piod_op = op;
    802 		io.piod_addr = &vector;
    803 		io.piod_len = sizeof(int);
    804 		io.piod_offs = p;
    805 
    806 		errno = 0;
    807 		SYSCALL_REQUIRE(ptrace(PT_IO, child, &io, sizeof(io)) == -1);
    808 		ATF_REQUIRE_EQ(errno, EINVAL);
    809 	}
    810 
    811 	DPRINTF("Before resuming the child process where it left off "
    812 	    "and without signal to be sent\n");
    813 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
    814 
    815 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
    816 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
    817 	    child);
    818 
    819 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
    820 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
    821 }
    822 
    823 #define BYTES_TRANSFER_EOF(test, operation)				\
    824 ATF_TC(test);								\
    825 ATF_TC_HEAD(test, tc)							\
    826 {									\
    827 	atf_tc_set_md_var(tc, "descr",					\
    828 	    "Verify bytes EOF byte transfer for the " operation		\
    829 	    " operation");						\
    830 }									\
    831 									\
    832 ATF_TC_BODY(test, tc)							\
    833 {									\
    834 									\
    835 	bytes_transfer_eof(operation);					\
    836 }
    837 
    838 BYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_i, "PT_READ_I")
    839 BYTES_TRANSFER_EOF(bytes_transfer_eof_pt_read_d, "PT_READ_D")
    840 BYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_i, "PT_WRITE_I")
    841 BYTES_TRANSFER_EOF(bytes_transfer_eof_pt_write_d, "PT_WRITE_D")
    842 
    843 BYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_i, "PIOD_READ_I")
    844 BYTES_TRANSFER_EOF(bytes_transfer_eof_piod_read_d, "PIOD_READ_D")
    845 BYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_i, "PIOD_WRITE_I")
    846 BYTES_TRANSFER_EOF(bytes_transfer_eof_piod_write_d, "PIOD_WRITE_D")
    847 
    848 
    849 #define ATF_TP_ADD_TCS_PTRACE_WAIT_BYTETRANSFER() \
    850 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8); \
    851 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16); \
    852 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32); \
    853 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64); \
    854 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8); \
    855 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16); \
    856 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32); \
    857 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64); \
    858 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8); \
    859 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16); \
    860 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32); \
    861 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64); \
    862 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8); \
    863 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16); \
    864 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32); \
    865 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64); \
    866 	ATF_TP_ADD_TC(tp, bytes_transfer_read_d); \
    867 	ATF_TP_ADD_TC(tp, bytes_transfer_read_i); \
    868 	ATF_TP_ADD_TC(tp, bytes_transfer_write_d); \
    869 	ATF_TP_ADD_TC(tp, bytes_transfer_write_i); \
    870 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_8_text); \
    871 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_16_text); \
    872 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_32_text); \
    873 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_d_64_text); \
    874 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_8_text); \
    875 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_16_text); \
    876 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_32_text); \
    877 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_i_64_text); \
    878 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_8_text); \
    879 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_16_text); \
    880 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_32_text); \
    881 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_d_64_text); \
    882 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_8_text); \
    883 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_16_text); \
    884 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_32_text); \
    885 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_write_i_64_text); \
    886 	ATF_TP_ADD_TC(tp, bytes_transfer_read_d_text); \
    887 	ATF_TP_ADD_TC(tp, bytes_transfer_read_i_text); \
    888 	ATF_TP_ADD_TC(tp, bytes_transfer_write_d_text); \
    889 	ATF_TP_ADD_TC(tp, bytes_transfer_write_i_text); \
    890 	ATF_TP_ADD_TC(tp, bytes_transfer_piod_read_auxv); \
    891 	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_i); \
    892 	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_read_d); \
    893 	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_i); \
    894 	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_pt_write_d); \
    895 	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_i); \
    896 	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_d); \
    897 	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_i); \
    898 	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_write_d); \
    899 	ATF_TP_ADD_TC(tp, bytes_transfer_alignment_piod_read_auxv); \
    900 	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_i); \
    901 	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_read_d); \
    902 	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_i); \
    903 	ATF_TP_ADD_TC(tp, bytes_transfer_eof_pt_write_d); \
    904 	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_i); \
    905 	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_read_d); \
    906 	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_i); \
    907 	ATF_TP_ADD_TC(tp, bytes_transfer_eof_piod_write_d);
    908