xref: /netbsd-src/tests/lib/libc/sys/t_ptrace_bytetransfer_wait.h (revision cacb90637f386e6d728228158d160e0b6c21ba06)
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
bytes_transfer_dummy(int a,int b,int c,int d)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
bytes_transfer(int operation,size_t size,enum bytes_transfer_type type)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
bytes_transfer_alignment(const char * operation)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
bytes_transfer_eof(const char * operation)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