t_ptrace_bytetransfer_wait.h revision 1.2 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