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