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