1 /* $NetBSD: t_ptrace_x86_wait.h,v 1.14 2019/06/04 12:17:05 mgorny Exp $ */ 2 3 /*- 4 * Copyright (c) 2016, 2017, 2018, 2019 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 #if defined(__i386__) || defined(__x86_64__) 30 union u { 31 unsigned long raw; 32 struct { 33 unsigned long local_dr0_breakpoint : 1; /* 0 */ 34 unsigned long global_dr0_breakpoint : 1; /* 1 */ 35 unsigned long local_dr1_breakpoint : 1; /* 2 */ 36 unsigned long global_dr1_breakpoint : 1; /* 3 */ 37 unsigned long local_dr2_breakpoint : 1; /* 4 */ 38 unsigned long global_dr2_breakpoint : 1; /* 5 */ 39 unsigned long local_dr3_breakpoint : 1; /* 6 */ 40 unsigned long global_dr3_breakpoint : 1; /* 7 */ 41 unsigned long local_exact_breakpt : 1; /* 8 */ 42 unsigned long global_exact_breakpt : 1; /* 9 */ 43 unsigned long reserved_10 : 1; /* 10 */ 44 unsigned long rest_trans_memory : 1; /* 11 */ 45 unsigned long reserved_12 : 1; /* 12 */ 46 unsigned long general_detect_enable : 1; /* 13 */ 47 unsigned long reserved_14 : 1; /* 14 */ 48 unsigned long reserved_15 : 1; /* 15 */ 49 unsigned long condition_dr0 : 2; /* 16-17 */ 50 unsigned long len_dr0 : 2; /* 18-19 */ 51 unsigned long condition_dr1 : 2; /* 20-21 */ 52 unsigned long len_dr1 : 2; /* 22-23 */ 53 unsigned long condition_dr2 : 2; /* 24-25 */ 54 unsigned long len_dr2 : 2; /* 26-27 */ 55 unsigned long condition_dr3 : 2; /* 28-29 */ 56 unsigned long len_dr3 : 2; /* 30-31 */ 57 } bits; 58 }; 59 60 ATF_TC(dbregs_print); 61 ATF_TC_HEAD(dbregs_print, tc) 62 { 63 atf_tc_set_md_var(tc, "descr", 64 "Verify plain PT_GETDBREGS with printing Debug Registers"); 65 } 66 67 ATF_TC_BODY(dbregs_print, tc) 68 { 69 const int exitval = 5; 70 const int sigval = SIGSTOP; 71 pid_t child, wpid; 72 #if defined(TWAIT_HAVE_STATUS) 73 int status; 74 #endif 75 struct dbreg r; 76 size_t i; 77 78 DPRINTF("Before forking process PID=%d\n", getpid()); 79 SYSCALL_REQUIRE((child = fork()) != -1); 80 if (child == 0) { 81 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 82 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 83 84 DPRINTF("Before raising %s from child\n", strsignal(sigval)); 85 FORKEE_ASSERT(raise(sigval) == 0); 86 87 DPRINTF("Before exiting of the child process\n"); 88 _exit(exitval); 89 } 90 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 91 92 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 93 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 94 95 validate_status_stopped(status, sigval); 96 97 DPRINTF("Call GETDBREGS for the child process\n"); 98 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &r, 0) != -1); 99 100 DPRINTF("State of the debug registers:\n"); 101 for (i = 0; i < __arraycount(r.dr); i++) 102 DPRINTF("r[%zu]=%" PRIxREGISTER "\n", i, r.dr[i]); 103 104 DPRINTF("Before resuming the child process where it left off and " 105 "without signal to be sent\n"); 106 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 107 108 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 109 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 110 111 validate_status_exited(status, exitval); 112 113 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 114 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 115 } 116 117 118 enum dbreg_preserve_mode { 119 dbreg_preserve_mode_none, 120 dbreg_preserve_mode_yield, 121 dbreg_preserve_mode_continued 122 }; 123 124 static void 125 dbreg_preserve(int reg, enum dbreg_preserve_mode mode) 126 { 127 const int exitval = 5; 128 const int sigval = SIGSTOP; 129 pid_t child, wpid; 130 #if defined(TWAIT_HAVE_STATUS) 131 int status; 132 #endif 133 struct dbreg r1; 134 struct dbreg r2; 135 size_t i; 136 int watchme; 137 138 if (!can_we_set_dbregs()) { 139 atf_tc_skip("Either run this test as root or set sysctl(3) " 140 "security.models.extensions.user_set_dbregs to 1"); 141 } 142 143 DPRINTF("Before forking process PID=%d\n", getpid()); 144 SYSCALL_REQUIRE((child = fork()) != -1); 145 if (child == 0) { 146 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 147 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 148 149 DPRINTF("Before raising %s from child\n", strsignal(sigval)); 150 FORKEE_ASSERT(raise(sigval) == 0); 151 152 if (mode == dbreg_preserve_mode_continued) { 153 DPRINTF("Before raising %s from child\n", 154 strsignal(sigval)); 155 FORKEE_ASSERT(raise(sigval) == 0); 156 } 157 158 DPRINTF("Before exiting of the child process\n"); 159 _exit(exitval); 160 } 161 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 162 163 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 164 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 165 166 validate_status_stopped(status, sigval); 167 168 DPRINTF("Call GETDBREGS for the child process (r1)\n"); 169 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1); 170 171 DPRINTF("State of the debug registers (r1):\n"); 172 for (i = 0; i < __arraycount(r1.dr); i++) 173 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]); 174 175 r1.dr[reg] = (long)(intptr_t)&watchme; 176 DPRINTF("Set DR0 (r1.dr[%d]) to new value %" PRIxREGISTER "\n", 177 reg, r1.dr[reg]); 178 179 DPRINTF("New state of the debug registers (r1):\n"); 180 for (i = 0; i < __arraycount(r1.dr); i++) 181 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]); 182 183 DPRINTF("Call SETDBREGS for the child process (r1)\n"); 184 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1); 185 186 switch (mode) { 187 case dbreg_preserve_mode_none: 188 break; 189 case dbreg_preserve_mode_yield: 190 DPRINTF("Yields a processor voluntarily and gives other " 191 "threads a chance to run without waiting for an " 192 "involuntary preemptive switch\n"); 193 sched_yield(); 194 break; 195 case dbreg_preserve_mode_continued: 196 DPRINTF("Call CONTINUE for the child process\n"); 197 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 198 199 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 200 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 201 202 validate_status_stopped(status, sigval); 203 break; 204 } 205 206 DPRINTF("Call GETDBREGS for the child process (r2)\n"); 207 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &r2, 0) != -1); 208 209 DPRINTF("Assert that (r1) and (r2) are the same\n"); 210 SYSCALL_REQUIRE(memcmp(&r1, &r2, sizeof(r1)) == 0); 211 212 DPRINTF("Before resuming the child process where it left off and " 213 "without signal to be sent\n"); 214 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 215 216 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 217 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 218 219 validate_status_exited(status, exitval); 220 221 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 222 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 223 } 224 225 226 ATF_TC(dbregs_preserve_dr0); 227 ATF_TC_HEAD(dbregs_preserve_dr0, tc) 228 { 229 atf_tc_set_md_var(tc, "descr", 230 "Verify that setting DR0 is preserved across ptrace(2) calls"); 231 } 232 233 ATF_TC_BODY(dbregs_preserve_dr0, tc) 234 { 235 dbreg_preserve(0, dbreg_preserve_mode_none); 236 } 237 238 ATF_TC(dbregs_preserve_dr1); 239 ATF_TC_HEAD(dbregs_preserve_dr1, tc) 240 { 241 atf_tc_set_md_var(tc, "descr", 242 "Verify that setting DR1 is preserved across ptrace(2) calls"); 243 } 244 245 ATF_TC_BODY(dbregs_preserve_dr1, tc) 246 { 247 dbreg_preserve(1, dbreg_preserve_mode_none); 248 } 249 250 ATF_TC(dbregs_preserve_dr2); 251 ATF_TC_HEAD(dbregs_preserve_dr2, tc) 252 { 253 atf_tc_set_md_var(tc, "descr", 254 "Verify that setting DR2 is preserved across ptrace(2) calls"); 255 } 256 257 ATF_TC_BODY(dbregs_preserve_dr2, tc) 258 { 259 dbreg_preserve(2, dbreg_preserve_mode_none); 260 } 261 262 ATF_TC(dbregs_preserve_dr3); 263 ATF_TC_HEAD(dbregs_preserve_dr3, tc) 264 { 265 atf_tc_set_md_var(tc, "descr", 266 "Verify that setting DR3 is preserved across ptrace(2) calls"); 267 } 268 269 ATF_TC_BODY(dbregs_preserve_dr3, tc) 270 { 271 dbreg_preserve(3, dbreg_preserve_mode_none); 272 } 273 274 ATF_TC(dbregs_preserve_dr0_yield); 275 ATF_TC_HEAD(dbregs_preserve_dr0_yield, tc) 276 { 277 atf_tc_set_md_var(tc, "descr", 278 "Verify that setting DR0 is preserved across ptrace(2) calls with " 279 "scheduler yield"); 280 } 281 282 ATF_TC_BODY(dbregs_preserve_dr0_yield, tc) 283 { 284 dbreg_preserve(0, dbreg_preserve_mode_yield); 285 } 286 287 ATF_TC(dbregs_preserve_dr1_yield); 288 ATF_TC_HEAD(dbregs_preserve_dr1_yield, tc) 289 { 290 atf_tc_set_md_var(tc, "descr", 291 "Verify that setting DR1 is preserved across ptrace(2) calls with " 292 "scheduler yield"); 293 } 294 295 ATF_TC_BODY(dbregs_preserve_dr1_yield, tc) 296 { 297 dbreg_preserve(0, dbreg_preserve_mode_yield); 298 } 299 300 ATF_TC(dbregs_preserve_dr2_yield); 301 ATF_TC_HEAD(dbregs_preserve_dr2_yield, tc) 302 { 303 atf_tc_set_md_var(tc, "descr", 304 "Verify that setting DR2 is preserved across ptrace(2) calls with " 305 "scheduler yield"); 306 } 307 308 ATF_TC_BODY(dbregs_preserve_dr2_yield, tc) 309 { 310 dbreg_preserve(0, dbreg_preserve_mode_yield); 311 } 312 313 314 ATF_TC(dbregs_preserve_dr3_yield); 315 ATF_TC_HEAD(dbregs_preserve_dr3_yield, tc) 316 { 317 atf_tc_set_md_var(tc, "descr", 318 "Verify that setting DR3 is preserved across ptrace(2) calls with " 319 "scheduler yield"); 320 } 321 322 ATF_TC_BODY(dbregs_preserve_dr3_yield, tc) 323 { 324 dbreg_preserve(3, dbreg_preserve_mode_yield); 325 } 326 327 ATF_TC(dbregs_preserve_dr0_continued); 328 ATF_TC_HEAD(dbregs_preserve_dr0_continued, tc) 329 { 330 atf_tc_set_md_var(tc, "descr", 331 "Verify that setting DR0 is preserved across ptrace(2) calls and " 332 "with continued child"); 333 } 334 335 ATF_TC_BODY(dbregs_preserve_dr0_continued, tc) 336 { 337 dbreg_preserve(0, dbreg_preserve_mode_continued); 338 } 339 340 ATF_TC(dbregs_preserve_dr1_continued); 341 ATF_TC_HEAD(dbregs_preserve_dr1_continued, tc) 342 { 343 atf_tc_set_md_var(tc, "descr", 344 "Verify that setting DR1 is preserved across ptrace(2) calls and " 345 "with continued child"); 346 } 347 348 ATF_TC_BODY(dbregs_preserve_dr1_continued, tc) 349 { 350 dbreg_preserve(1, dbreg_preserve_mode_continued); 351 } 352 353 ATF_TC(dbregs_preserve_dr2_continued); 354 ATF_TC_HEAD(dbregs_preserve_dr2_continued, tc) 355 { 356 atf_tc_set_md_var(tc, "descr", 357 "Verify that setting DR2 is preserved across ptrace(2) calls and " 358 "with continued child"); 359 } 360 361 ATF_TC_BODY(dbregs_preserve_dr2_continued, tc) 362 { 363 dbreg_preserve(2, dbreg_preserve_mode_continued); 364 } 365 366 ATF_TC(dbregs_preserve_dr3_continued); 367 ATF_TC_HEAD(dbregs_preserve_dr3_continued, tc) 368 { 369 atf_tc_set_md_var(tc, "descr", 370 "Verify that setting DR3 is preserved across ptrace(2) calls and " 371 "with continued child"); 372 } 373 374 ATF_TC_BODY(dbregs_preserve_dr3_continued, tc) 375 { 376 dbreg_preserve(3, dbreg_preserve_mode_continued); 377 } 378 379 380 static void 381 dbregs_trap_variable(int reg, int cond, int len, bool write) 382 { 383 const int exitval = 5; 384 const int sigval = SIGSTOP; 385 pid_t child, wpid; 386 #if defined(TWAIT_HAVE_STATUS) 387 int status; 388 #endif 389 struct dbreg r1; 390 size_t i; 391 volatile int watchme = 0; 392 union u dr7; 393 394 struct ptrace_siginfo info; 395 memset(&info, 0, sizeof(info)); 396 397 if (!can_we_set_dbregs()) { 398 atf_tc_skip("Either run this test as root or set sysctl(3) " 399 "security.models.extensions.user_set_dbregs to 1"); 400 } 401 402 dr7.raw = 0; 403 switch (reg) { 404 case 0: 405 dr7.bits.global_dr0_breakpoint = 1; 406 dr7.bits.condition_dr0 = cond; 407 dr7.bits.len_dr0 = len; 408 break; 409 case 1: 410 dr7.bits.global_dr1_breakpoint = 1; 411 dr7.bits.condition_dr1 = cond; 412 dr7.bits.len_dr1 = len; 413 break; 414 case 2: 415 dr7.bits.global_dr2_breakpoint = 1; 416 dr7.bits.condition_dr2 = cond; 417 dr7.bits.len_dr2 = len; 418 break; 419 case 3: 420 dr7.bits.global_dr3_breakpoint = 1; 421 dr7.bits.condition_dr3 = cond; 422 dr7.bits.len_dr3 = len; 423 break; 424 } 425 426 DPRINTF("Before forking process PID=%d\n", getpid()); 427 SYSCALL_REQUIRE((child = fork()) != -1); 428 if (child == 0) { 429 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 430 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 431 432 DPRINTF("Before raising %s from child\n", strsignal(sigval)); 433 FORKEE_ASSERT(raise(sigval) == 0); 434 435 if (write) 436 watchme = 1; 437 else 438 printf("watchme=%d\n", watchme); 439 440 DPRINTF("Before raising %s from child\n", strsignal(sigval)); 441 FORKEE_ASSERT(raise(sigval) == 0); 442 443 DPRINTF("Before exiting of the child process\n"); 444 _exit(exitval); 445 } 446 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 447 448 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 449 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 450 451 validate_status_stopped(status, sigval); 452 453 DPRINTF("Call GETDBREGS for the child process (r1)\n"); 454 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1); 455 456 DPRINTF("State of the debug registers (r1):\n"); 457 for (i = 0; i < __arraycount(r1.dr); i++) 458 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]); 459 460 r1.dr[reg] = (long)(intptr_t)&watchme; 461 DPRINTF("Set DR%d (r1.dr[%d]) to new value %" PRIxREGISTER "\n", 462 reg, reg, r1.dr[reg]); 463 464 r1.dr[7] = dr7.raw; 465 DPRINTF("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n", 466 r1.dr[7]); 467 468 DPRINTF("New state of the debug registers (r1):\n"); 469 for (i = 0; i < __arraycount(r1.dr); i++) 470 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]); 471 472 DPRINTF("Call SETDBREGS for the child process (r1)\n"); 473 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1); 474 475 DPRINTF("Call CONTINUE for the child process\n"); 476 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 477 478 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 479 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 480 481 validate_status_stopped(status, SIGTRAP); 482 483 DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 484 SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 485 486 DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 487 DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 488 info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 489 info.psi_siginfo.si_errno); 490 491 DPRINTF("Before checking siginfo_t\n"); 492 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 493 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_DBREG); 494 495 DPRINTF("Call CONTINUE for the child process\n"); 496 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 497 498 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 499 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 500 501 validate_status_stopped(status, sigval); 502 503 DPRINTF("Before resuming the child process where it left off and " 504 "without signal to be sent\n"); 505 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 506 507 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 508 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 509 510 validate_status_exited(status, exitval); 511 512 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 513 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 514 } 515 516 ATF_TC(dbregs_dr0_trap_variable_writeonly_byte); 517 ATF_TC_HEAD(dbregs_dr0_trap_variable_writeonly_byte, tc) 518 { 519 atf_tc_set_md_var(tc, "descr", 520 "Verify that setting trap with DR0 triggers SIGTRAP " 521 "(break on data writes only and 1 byte mode)"); 522 } 523 524 ATF_TC_BODY(dbregs_dr0_trap_variable_writeonly_byte, tc) 525 { 526 /* 0b01 -- break on data write only */ 527 /* 0b00 -- 1 byte */ 528 529 dbregs_trap_variable(0, 1, 0, true); 530 } 531 532 ATF_TC(dbregs_dr1_trap_variable_writeonly_byte); 533 ATF_TC_HEAD(dbregs_dr1_trap_variable_writeonly_byte, tc) 534 { 535 atf_tc_set_md_var(tc, "descr", 536 "Verify that setting trap with DR1 triggers SIGTRAP " 537 "(break on data writes only and 1 byte mode)"); 538 } 539 540 ATF_TC_BODY(dbregs_dr1_trap_variable_writeonly_byte, tc) 541 { 542 /* 0b01 -- break on data write only */ 543 /* 0b00 -- 1 byte */ 544 545 dbregs_trap_variable(1, 1, 0, true); 546 } 547 548 ATF_TC(dbregs_dr2_trap_variable_writeonly_byte); 549 ATF_TC_HEAD(dbregs_dr2_trap_variable_writeonly_byte, tc) 550 { 551 atf_tc_set_md_var(tc, "descr", 552 "Verify that setting trap with DR2 triggers SIGTRAP " 553 "(break on data writes only and 1 byte mode)"); 554 } 555 556 ATF_TC_BODY(dbregs_dr2_trap_variable_writeonly_byte, tc) 557 { 558 /* 0b01 -- break on data write only */ 559 /* 0b00 -- 1 byte */ 560 561 dbregs_trap_variable(2, 1, 0, true); 562 } 563 564 ATF_TC(dbregs_dr3_trap_variable_writeonly_byte); 565 ATF_TC_HEAD(dbregs_dr3_trap_variable_writeonly_byte, tc) 566 { 567 atf_tc_set_md_var(tc, "descr", 568 "Verify that setting trap with DR3 triggers SIGTRAP " 569 "(break on data writes only and 1 byte mode)"); 570 } 571 572 ATF_TC_BODY(dbregs_dr3_trap_variable_writeonly_byte, tc) 573 { 574 /* 0b01 -- break on data write only */ 575 /* 0b00 -- 1 byte */ 576 577 dbregs_trap_variable(3, 1, 0, true); 578 } 579 580 ATF_TC(dbregs_dr0_trap_variable_writeonly_2bytes); 581 ATF_TC_HEAD(dbregs_dr0_trap_variable_writeonly_2bytes, tc) 582 { 583 atf_tc_set_md_var(tc, "descr", 584 "Verify that setting trap with DR0 triggers SIGTRAP " 585 "(break on data writes only and 2 bytes mode)"); 586 } 587 588 ATF_TC_BODY(dbregs_dr0_trap_variable_writeonly_2bytes, tc) 589 { 590 /* 0b01 -- break on data write only */ 591 /* 0b01 -- 2 bytes */ 592 593 dbregs_trap_variable(0, 1, 1, true); 594 } 595 596 ATF_TC(dbregs_dr1_trap_variable_writeonly_2bytes); 597 ATF_TC_HEAD(dbregs_dr1_trap_variable_writeonly_2bytes, tc) 598 { 599 atf_tc_set_md_var(tc, "descr", 600 "Verify that setting trap with DR1 triggers SIGTRAP " 601 "(break on data writes only and 2 bytes mode)"); 602 } 603 604 ATF_TC_BODY(dbregs_dr1_trap_variable_writeonly_2bytes, tc) 605 { 606 /* 0b01 -- break on data write only */ 607 /* 0b01 -- 2 bytes */ 608 609 dbregs_trap_variable(1, 1, 1, true); 610 } 611 612 ATF_TC(dbregs_dr2_trap_variable_writeonly_2bytes); 613 ATF_TC_HEAD(dbregs_dr2_trap_variable_writeonly_2bytes, tc) 614 { 615 atf_tc_set_md_var(tc, "descr", 616 "Verify that setting trap with DR2 triggers SIGTRAP " 617 "(break on data writes only and 2 bytes mode)"); 618 } 619 620 ATF_TC_BODY(dbregs_dr2_trap_variable_writeonly_2bytes, tc) 621 { 622 /* 0b01 -- break on data write only */ 623 /* 0b01 -- 2 bytes */ 624 625 dbregs_trap_variable(2, 1, 1, true); 626 } 627 628 ATF_TC(dbregs_dr3_trap_variable_writeonly_2bytes); 629 ATF_TC_HEAD(dbregs_dr3_trap_variable_writeonly_2bytes, tc) 630 { 631 atf_tc_set_md_var(tc, "descr", 632 "Verify that setting trap with DR3 triggers SIGTRAP " 633 "(break on data writes only and 2 bytes mode)"); 634 } 635 636 ATF_TC_BODY(dbregs_dr3_trap_variable_writeonly_2bytes, tc) 637 { 638 /* 0b01 -- break on data write only */ 639 /* 0b01 -- 2 bytes */ 640 641 dbregs_trap_variable(3, 1, 1, true); 642 } 643 644 ATF_TC(dbregs_dr0_trap_variable_writeonly_4bytes); 645 ATF_TC_HEAD(dbregs_dr0_trap_variable_writeonly_4bytes, tc) 646 { 647 atf_tc_set_md_var(tc, "descr", 648 "Verify that setting trap with DR0 triggers SIGTRAP " 649 "(break on data writes only and 4 bytes mode)"); 650 } 651 652 ATF_TC_BODY(dbregs_dr0_trap_variable_writeonly_4bytes, tc) 653 { 654 /* 0b01 -- break on data write only */ 655 /* 0b11 -- 4 bytes */ 656 657 dbregs_trap_variable(0, 1, 3, true); 658 } 659 660 ATF_TC(dbregs_dr1_trap_variable_writeonly_4bytes); 661 ATF_TC_HEAD(dbregs_dr1_trap_variable_writeonly_4bytes, tc) 662 { 663 atf_tc_set_md_var(tc, "descr", 664 "Verify that setting trap with DR1 triggers SIGTRAP " 665 "(break on data writes only and 4 bytes mode)"); 666 } 667 668 ATF_TC_BODY(dbregs_dr1_trap_variable_writeonly_4bytes, tc) 669 { 670 /* 0b01 -- break on data write only */ 671 /* 0b11 -- 4 bytes */ 672 673 dbregs_trap_variable(1, 1, 3, true); 674 } 675 676 ATF_TC(dbregs_dr2_trap_variable_writeonly_4bytes); 677 ATF_TC_HEAD(dbregs_dr2_trap_variable_writeonly_4bytes, tc) 678 { 679 atf_tc_set_md_var(tc, "descr", 680 "Verify that setting trap with DR2 triggers SIGTRAP " 681 "(break on data writes only and 4 bytes mode)"); 682 } 683 684 ATF_TC_BODY(dbregs_dr2_trap_variable_writeonly_4bytes, tc) 685 { 686 /* 0b01 -- break on data write only */ 687 /* 0b11 -- 4 bytes */ 688 689 dbregs_trap_variable(2, 1, 3, true); 690 } 691 692 ATF_TC(dbregs_dr3_trap_variable_writeonly_4bytes); 693 ATF_TC_HEAD(dbregs_dr3_trap_variable_writeonly_4bytes, tc) 694 { 695 atf_tc_set_md_var(tc, "descr", 696 "Verify that setting trap with DR3 triggers SIGTRAP " 697 "(break on data writes only and 4 bytes mode)"); 698 } 699 700 ATF_TC_BODY(dbregs_dr3_trap_variable_writeonly_4bytes, tc) 701 { 702 /* 0b01 -- break on data write only */ 703 /* 0b11 -- 4 bytes */ 704 705 dbregs_trap_variable(3, 1, 3, true); 706 } 707 708 ATF_TC(dbregs_dr0_trap_variable_readwrite_write_byte); 709 ATF_TC_HEAD(dbregs_dr0_trap_variable_readwrite_write_byte, tc) 710 { 711 atf_tc_set_md_var(tc, "descr", 712 "Verify that setting trap with DR0 triggers SIGTRAP " 713 "(break on data read/write trap in read 1 byte mode)"); 714 } 715 716 ATF_TC_BODY(dbregs_dr0_trap_variable_readwrite_write_byte, tc) 717 { 718 /* 0b11 -- break on data write&read */ 719 /* 0b00 -- 1 byte */ 720 721 dbregs_trap_variable(0, 3, 0, true); 722 } 723 724 ATF_TC(dbregs_dr1_trap_variable_readwrite_write_byte); 725 ATF_TC_HEAD(dbregs_dr1_trap_variable_readwrite_write_byte, tc) 726 { 727 atf_tc_set_md_var(tc, "descr", 728 "Verify that setting trap with DR1 triggers SIGTRAP " 729 "(break on data read/write trap in read 1 byte mode)"); 730 } 731 732 ATF_TC_BODY(dbregs_dr1_trap_variable_readwrite_write_byte, tc) 733 { 734 /* 0b11 -- break on data write&read */ 735 /* 0b00 -- 1 byte */ 736 737 dbregs_trap_variable(1, 3, 0, true); 738 } 739 740 ATF_TC(dbregs_dr2_trap_variable_readwrite_write_byte); 741 ATF_TC_HEAD(dbregs_dr2_trap_variable_readwrite_write_byte, tc) 742 { 743 atf_tc_set_md_var(tc, "descr", 744 "Verify that setting trap with DR2 triggers SIGTRAP " 745 "(break on data read/write trap in read 1 byte mode)"); 746 } 747 748 ATF_TC_BODY(dbregs_dr2_trap_variable_readwrite_write_byte, tc) 749 { 750 /* 0b11 -- break on data write&read */ 751 /* 0b00 -- 1 byte */ 752 753 dbregs_trap_variable(2, 3, 0, true); 754 } 755 756 ATF_TC(dbregs_dr3_trap_variable_readwrite_write_byte); 757 ATF_TC_HEAD(dbregs_dr3_trap_variable_readwrite_write_byte, tc) 758 { 759 atf_tc_set_md_var(tc, "descr", 760 "Verify that setting trap with DR3 triggers SIGTRAP " 761 "(break on data read/write trap in read 1 byte mode)"); 762 } 763 764 ATF_TC_BODY(dbregs_dr3_trap_variable_readwrite_write_byte, tc) 765 { 766 /* 0b11 -- break on data write&read */ 767 /* 0b00 -- 1 byte */ 768 769 dbregs_trap_variable(3, 3, 0, true); 770 } 771 772 ATF_TC(dbregs_dr0_trap_variable_readwrite_write_2bytes); 773 ATF_TC_HEAD(dbregs_dr0_trap_variable_readwrite_write_2bytes, tc) 774 { 775 atf_tc_set_md_var(tc, "descr", 776 "Verify that setting trap with DR0 triggers SIGTRAP " 777 "(break on data read/write trap in read 2 bytes mode)"); 778 } 779 780 ATF_TC_BODY(dbregs_dr0_trap_variable_readwrite_write_2bytes, tc) 781 { 782 /* 0b11 -- break on data write&read */ 783 /* 0b01 -- 2 bytes */ 784 785 dbregs_trap_variable(0, 3, 1, true); 786 } 787 788 ATF_TC(dbregs_dr1_trap_variable_readwrite_write_2bytes); 789 ATF_TC_HEAD(dbregs_dr1_trap_variable_readwrite_write_2bytes, tc) 790 { 791 atf_tc_set_md_var(tc, "descr", 792 "Verify that setting trap with DR1 triggers SIGTRAP " 793 "(break on data read/write trap in read 2 bytes mode)"); 794 } 795 796 ATF_TC_BODY(dbregs_dr1_trap_variable_readwrite_write_2bytes, tc) 797 { 798 /* 0b11 -- break on data write&read */ 799 /* 0b01 -- 2 bytes */ 800 801 dbregs_trap_variable(1, 3, 1, true); 802 } 803 804 ATF_TC(dbregs_dr2_trap_variable_readwrite_write_2bytes); 805 ATF_TC_HEAD(dbregs_dr2_trap_variable_readwrite_write_2bytes, tc) 806 { 807 atf_tc_set_md_var(tc, "descr", 808 "Verify that setting trap with DR2 triggers SIGTRAP " 809 "(break on data read/write trap in read 2 bytes mode)"); 810 } 811 812 ATF_TC_BODY(dbregs_dr2_trap_variable_readwrite_write_2bytes, tc) 813 { 814 /* 0b11 -- break on data write&read */ 815 /* 0b01 -- 2 bytes */ 816 817 dbregs_trap_variable(2, 3, 1, true); 818 } 819 820 ATF_TC(dbregs_dr3_trap_variable_readwrite_write_2bytes); 821 ATF_TC_HEAD(dbregs_dr3_trap_variable_readwrite_write_2bytes, tc) 822 { 823 atf_tc_set_md_var(tc, "descr", 824 "Verify that setting trap with DR3 triggers SIGTRAP " 825 "(break on data read/write trap in read 2 bytes mode)"); 826 } 827 828 ATF_TC_BODY(dbregs_dr3_trap_variable_readwrite_write_2bytes, tc) 829 { 830 /* 0b11 -- break on data write&read */ 831 /* 0b01 -- 2 bytes */ 832 833 dbregs_trap_variable(3, 3, 1, true); 834 } 835 836 ATF_TC(dbregs_dr0_trap_variable_readwrite_write_4bytes); 837 ATF_TC_HEAD(dbregs_dr0_trap_variable_readwrite_write_4bytes, tc) 838 { 839 atf_tc_set_md_var(tc, "descr", 840 "Verify that setting trap with DR0 triggers SIGTRAP " 841 "(break on data read/write trap in read 4 bytes mode)"); 842 } 843 844 ATF_TC_BODY(dbregs_dr0_trap_variable_readwrite_write_4bytes, tc) 845 { 846 /* 0b11 -- break on data write&read */ 847 /* 0b11 -- 4 bytes */ 848 849 dbregs_trap_variable(0, 3, 3, true); 850 } 851 852 ATF_TC(dbregs_dr1_trap_variable_readwrite_write_4bytes); 853 ATF_TC_HEAD(dbregs_dr1_trap_variable_readwrite_write_4bytes, tc) 854 { 855 atf_tc_set_md_var(tc, "descr", 856 "Verify that setting trap with DR1 triggers SIGTRAP " 857 "(break on data read/write trap in read 4 bytes mode)"); 858 } 859 860 ATF_TC_BODY(dbregs_dr1_trap_variable_readwrite_write_4bytes, tc) 861 { 862 /* 0b11 -- break on data write&read */ 863 /* 0b11 -- 4 bytes */ 864 865 dbregs_trap_variable(1, 3, 3, true); 866 } 867 868 ATF_TC(dbregs_dr2_trap_variable_readwrite_write_4bytes); 869 ATF_TC_HEAD(dbregs_dr2_trap_variable_readwrite_write_4bytes, tc) 870 { 871 atf_tc_set_md_var(tc, "descr", 872 "Verify that setting trap with DR2 triggers SIGTRAP " 873 "(break on data read/write trap in read 4 bytes mode)"); 874 } 875 876 ATF_TC_BODY(dbregs_dr2_trap_variable_readwrite_write_4bytes, tc) 877 { 878 /* 0b11 -- break on data write&read */ 879 /* 0b11 -- 4 bytes */ 880 881 dbregs_trap_variable(2, 3, 3, true); 882 } 883 884 ATF_TC(dbregs_dr3_trap_variable_readwrite_write_4bytes); 885 ATF_TC_HEAD(dbregs_dr3_trap_variable_readwrite_write_4bytes, tc) 886 { 887 atf_tc_set_md_var(tc, "descr", 888 "Verify that setting trap with DR3 triggers SIGTRAP " 889 "(break on data read/write trap in read 4 bytes mode)"); 890 } 891 892 ATF_TC_BODY(dbregs_dr3_trap_variable_readwrite_write_4bytes, tc) 893 { 894 /* 0b11 -- break on data write&read */ 895 /* 0b11 -- 4 bytes */ 896 897 dbregs_trap_variable(3, 3, 3, true); 898 } 899 900 ATF_TC(dbregs_dr0_trap_variable_readwrite_read_byte); 901 ATF_TC_HEAD(dbregs_dr0_trap_variable_readwrite_read_byte, tc) 902 { 903 atf_tc_set_md_var(tc, "descr", 904 "Verify that setting trap with DR0 triggers SIGTRAP " 905 "(break on data read/write trap in write 1 byte mode)"); 906 } 907 908 ATF_TC_BODY(dbregs_dr0_trap_variable_readwrite_read_byte, tc) 909 { 910 /* 0b11 -- break on data write&read */ 911 /* 0b00 -- 1 byte */ 912 913 dbregs_trap_variable(0, 3, 0, false); 914 } 915 916 ATF_TC(dbregs_dr1_trap_variable_readwrite_read_byte); 917 ATF_TC_HEAD(dbregs_dr1_trap_variable_readwrite_read_byte, tc) 918 { 919 atf_tc_set_md_var(tc, "descr", 920 "Verify that setting trap with DR1 triggers SIGTRAP " 921 "(break on data read/write trap in write 1 byte mode)"); 922 } 923 924 ATF_TC_BODY(dbregs_dr1_trap_variable_readwrite_read_byte, tc) 925 { 926 /* 0b11 -- break on data write&read */ 927 /* 0b00 -- 1 byte */ 928 929 dbregs_trap_variable(1, 3, 0, false); 930 } 931 932 ATF_TC(dbregs_dr2_trap_variable_readwrite_read_byte); 933 ATF_TC_HEAD(dbregs_dr2_trap_variable_readwrite_read_byte, tc) 934 { 935 atf_tc_set_md_var(tc, "descr", 936 "Verify that setting trap with DR2 triggers SIGTRAP " 937 "(break on data read/write trap in write 1 byte mode)"); 938 } 939 940 ATF_TC_BODY(dbregs_dr2_trap_variable_readwrite_read_byte, tc) 941 { 942 /* 0b11 -- break on data write&read */ 943 /* 0b00 -- 1 byte */ 944 945 dbregs_trap_variable(2, 3, 0, false); 946 } 947 948 ATF_TC(dbregs_dr3_trap_variable_readwrite_read_byte); 949 ATF_TC_HEAD(dbregs_dr3_trap_variable_readwrite_read_byte, tc) 950 { 951 atf_tc_set_md_var(tc, "descr", 952 "Verify that setting trap with DR3 triggers SIGTRAP " 953 "(break on data read/write trap in write 1 byte mode)"); 954 } 955 956 ATF_TC_BODY(dbregs_dr3_trap_variable_readwrite_read_byte, tc) 957 { 958 /* 0b11 -- break on data write&read */ 959 /* 0b00 -- 1 byte */ 960 961 dbregs_trap_variable(3, 3, 0, false); 962 } 963 964 ATF_TC(dbregs_dr0_trap_variable_readwrite_read_2bytes); 965 ATF_TC_HEAD(dbregs_dr0_trap_variable_readwrite_read_2bytes, tc) 966 { 967 atf_tc_set_md_var(tc, "descr", 968 "Verify that setting trap with DR0 triggers SIGTRAP " 969 "(break on data read/write trap in write 2 bytes mode)"); 970 } 971 972 ATF_TC_BODY(dbregs_dr0_trap_variable_readwrite_read_2bytes, tc) 973 { 974 /* 0b11 -- break on data write&read */ 975 /* 0b01 -- 2 bytes */ 976 977 dbregs_trap_variable(0, 3, 1, false); 978 } 979 980 ATF_TC(dbregs_dr1_trap_variable_readwrite_read_2bytes); 981 ATF_TC_HEAD(dbregs_dr1_trap_variable_readwrite_read_2bytes, tc) 982 { 983 atf_tc_set_md_var(tc, "descr", 984 "Verify that setting trap with DR1 triggers SIGTRAP " 985 "(break on data read/write trap in write 2 bytes mode)"); 986 } 987 988 ATF_TC_BODY(dbregs_dr1_trap_variable_readwrite_read_2bytes, tc) 989 { 990 /* 0b11 -- break on data write&read */ 991 /* 0b01 -- 2 bytes */ 992 993 dbregs_trap_variable(1, 3, 1, false); 994 } 995 996 ATF_TC(dbregs_dr2_trap_variable_readwrite_read_2bytes); 997 ATF_TC_HEAD(dbregs_dr2_trap_variable_readwrite_read_2bytes, tc) 998 { 999 atf_tc_set_md_var(tc, "descr", 1000 "Verify that setting trap with DR2 triggers SIGTRAP " 1001 "(break on data read/write trap in write 2 bytes mode)"); 1002 } 1003 1004 ATF_TC_BODY(dbregs_dr2_trap_variable_readwrite_read_2bytes, tc) 1005 { 1006 /* 0b11 -- break on data write&read */ 1007 /* 0b01 -- 2 bytes */ 1008 1009 dbregs_trap_variable(2, 3, 1, false); 1010 } 1011 1012 ATF_TC(dbregs_dr3_trap_variable_readwrite_read_2bytes); 1013 ATF_TC_HEAD(dbregs_dr3_trap_variable_readwrite_read_2bytes, tc) 1014 { 1015 atf_tc_set_md_var(tc, "descr", 1016 "Verify that setting trap with DR3 triggers SIGTRAP " 1017 "(break on data read/write trap in write 2 bytes mode)"); 1018 } 1019 1020 ATF_TC_BODY(dbregs_dr3_trap_variable_readwrite_read_2bytes, tc) 1021 { 1022 /* 0b11 -- break on data write&read */ 1023 /* 0b01 -- 2 bytes */ 1024 1025 dbregs_trap_variable(3, 3, 1, false); 1026 } 1027 1028 ATF_TC(dbregs_dr0_trap_variable_readwrite_read_4bytes); 1029 ATF_TC_HEAD(dbregs_dr0_trap_variable_readwrite_read_4bytes, tc) 1030 { 1031 atf_tc_set_md_var(tc, "descr", 1032 "Verify that setting trap with DR0 triggers SIGTRAP " 1033 "(break on data read/write trap in write 4 bytes mode)"); 1034 } 1035 1036 ATF_TC_BODY(dbregs_dr0_trap_variable_readwrite_read_4bytes, tc) 1037 { 1038 /* 0b11 -- break on data write&read */ 1039 /* 0b11 -- 4 bytes */ 1040 1041 dbregs_trap_variable(0, 3, 3, false); 1042 } 1043 1044 ATF_TC(dbregs_dr1_trap_variable_readwrite_read_4bytes); 1045 ATF_TC_HEAD(dbregs_dr1_trap_variable_readwrite_read_4bytes, tc) 1046 { 1047 atf_tc_set_md_var(tc, "descr", 1048 "Verify that setting trap with DR1 triggers SIGTRAP " 1049 "(break on data read/write trap in write 4 bytes mode)"); 1050 } 1051 1052 ATF_TC_BODY(dbregs_dr1_trap_variable_readwrite_read_4bytes, tc) 1053 { 1054 /* 0b11 -- break on data write&read */ 1055 /* 0b11 -- 4 bytes */ 1056 1057 dbregs_trap_variable(1, 3, 3, false); 1058 } 1059 1060 ATF_TC(dbregs_dr2_trap_variable_readwrite_read_4bytes); 1061 ATF_TC_HEAD(dbregs_dr2_trap_variable_readwrite_read_4bytes, tc) 1062 { 1063 atf_tc_set_md_var(tc, "descr", 1064 "Verify that setting trap with DR2 triggers SIGTRAP " 1065 "(break on data read/write trap in write 4 bytes mode)"); 1066 } 1067 1068 ATF_TC_BODY(dbregs_dr2_trap_variable_readwrite_read_4bytes, tc) 1069 { 1070 /* 0b11 -- break on data write&read */ 1071 /* 0b11 -- 4 bytes */ 1072 1073 dbregs_trap_variable(2, 3, 3, false); 1074 } 1075 1076 ATF_TC(dbregs_dr3_trap_variable_readwrite_read_4bytes); 1077 ATF_TC_HEAD(dbregs_dr3_trap_variable_readwrite_read_4bytes, tc) 1078 { 1079 atf_tc_set_md_var(tc, "descr", 1080 "Verify that setting trap with DR3 triggers SIGTRAP " 1081 "(break on data read/write trap in write 4 bytes mode)"); 1082 } 1083 1084 ATF_TC_BODY(dbregs_dr3_trap_variable_readwrite_read_4bytes, tc) 1085 { 1086 /* 0b11 -- break on data write&read */ 1087 /* 0b11 -- 4 bytes */ 1088 1089 dbregs_trap_variable(3, 3, 3, false); 1090 } 1091 1092 #if defined(HAVE_DBREGS) 1093 ATF_TC(dbregs_dr0_trap_code); 1094 ATF_TC_HEAD(dbregs_dr0_trap_code, tc) 1095 { 1096 atf_tc_set_md_var(tc, "descr", 1097 "Verify that setting trap with DR0 triggers SIGTRAP " 1098 "(break on code execution trap)"); 1099 } 1100 1101 ATF_TC_BODY(dbregs_dr0_trap_code, tc) 1102 { 1103 const int exitval = 5; 1104 const int sigval = SIGSTOP; 1105 pid_t child, wpid; 1106 #if defined(TWAIT_HAVE_STATUS) 1107 int status; 1108 #endif 1109 struct dbreg r1; 1110 size_t i; 1111 volatile int watchme = 1; 1112 union u dr7; 1113 1114 struct ptrace_siginfo info; 1115 memset(&info, 0, sizeof(info)); 1116 1117 if (!can_we_set_dbregs()) { 1118 atf_tc_skip("Either run this test as root or set sysctl(3) " 1119 "security.models.extensions.user_set_dbregs to 1"); 1120 } 1121 1122 dr7.raw = 0; 1123 dr7.bits.global_dr0_breakpoint = 1; 1124 dr7.bits.condition_dr0 = 0; /* 0b00 -- break on code execution */ 1125 dr7.bits.len_dr0 = 0; /* 0b00 -- 1 byte */ 1126 1127 DPRINTF("Before forking process PID=%d\n", getpid()); 1128 SYSCALL_REQUIRE((child = fork()) != -1); 1129 if (child == 0) { 1130 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1131 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1132 1133 DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1134 FORKEE_ASSERT(raise(sigval) == 0); 1135 1136 printf("check_happy(%d)=%d\n", watchme, check_happy(watchme)); 1137 1138 DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1139 FORKEE_ASSERT(raise(sigval) == 0); 1140 1141 DPRINTF("Before exiting of the child process\n"); 1142 _exit(exitval); 1143 } 1144 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1145 1146 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1147 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1148 1149 validate_status_stopped(status, sigval); 1150 1151 DPRINTF("Call GETDBREGS for the child process (r1)\n"); 1152 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1); 1153 1154 DPRINTF("State of the debug registers (r1):\n"); 1155 for (i = 0; i < __arraycount(r1.dr); i++) 1156 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]); 1157 1158 r1.dr[0] = (long)(intptr_t)check_happy; 1159 DPRINTF("Set DR0 (r1.dr[0]) to new value %" PRIxREGISTER "\n", 1160 r1.dr[0]); 1161 1162 r1.dr[7] = dr7.raw; 1163 DPRINTF("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n", 1164 r1.dr[7]); 1165 1166 DPRINTF("New state of the debug registers (r1):\n"); 1167 for (i = 0; i < __arraycount(r1.dr); i++) 1168 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]); 1169 1170 DPRINTF("Call SETDBREGS for the child process (r1)\n"); 1171 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1); 1172 1173 DPRINTF("Call CONTINUE for the child process\n"); 1174 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1175 1176 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1177 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1178 1179 validate_status_stopped(status, SIGTRAP); 1180 1181 DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 1182 SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 1183 1184 DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1185 DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 1186 info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1187 info.psi_siginfo.si_errno); 1188 1189 DPRINTF("Before checking siginfo_t\n"); 1190 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 1191 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_DBREG); 1192 1193 DPRINTF("Remove code trap from check_happy=%p\n", check_happy); 1194 dr7.bits.global_dr0_breakpoint = 0; 1195 r1.dr[7] = dr7.raw; 1196 DPRINTF("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n", 1197 r1.dr[7]); 1198 1199 DPRINTF("Call SETDBREGS for the child process (r1)\n"); 1200 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1); 1201 1202 DPRINTF("Call CONTINUE for the child process\n"); 1203 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1204 1205 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1206 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1207 1208 validate_status_stopped(status, sigval); 1209 1210 DPRINTF("Before resuming the child process where it left off and " 1211 "without signal to be sent\n"); 1212 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1213 1214 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1215 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1216 1217 validate_status_exited(status, exitval); 1218 1219 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1220 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 1221 } 1222 #endif 1223 1224 #if defined(HAVE_DBREGS) 1225 ATF_TC(dbregs_dr1_trap_code); 1226 ATF_TC_HEAD(dbregs_dr1_trap_code, tc) 1227 { 1228 atf_tc_set_md_var(tc, "descr", 1229 "Verify that setting trap with DR1 triggers SIGTRAP " 1230 "(break on code execution trap)"); 1231 } 1232 1233 ATF_TC_BODY(dbregs_dr1_trap_code, tc) 1234 { 1235 const int exitval = 5; 1236 const int sigval = SIGSTOP; 1237 pid_t child, wpid; 1238 #if defined(TWAIT_HAVE_STATUS) 1239 int status; 1240 #endif 1241 struct dbreg r1; 1242 size_t i; 1243 volatile int watchme = 1; 1244 union u dr7; 1245 1246 struct ptrace_siginfo info; 1247 memset(&info, 0, sizeof(info)); 1248 1249 if (!can_we_set_dbregs()) { 1250 atf_tc_skip("Either run this test as root or set sysctl(3) " 1251 "security.models.extensions.user_set_dbregs to 1"); 1252 } 1253 1254 dr7.raw = 0; 1255 dr7.bits.global_dr1_breakpoint = 1; 1256 dr7.bits.condition_dr1 = 0; /* 0b00 -- break on code execution */ 1257 dr7.bits.len_dr1 = 0; /* 0b00 -- 1 byte */ 1258 1259 DPRINTF("Before forking process PID=%d\n", getpid()); 1260 SYSCALL_REQUIRE((child = fork()) != -1); 1261 if (child == 0) { 1262 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1263 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1264 1265 DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1266 FORKEE_ASSERT(raise(sigval) == 0); 1267 1268 printf("check_happy(%d)=%d\n", watchme, check_happy(watchme)); 1269 1270 DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1271 FORKEE_ASSERT(raise(sigval) == 0); 1272 1273 DPRINTF("Before exiting of the child process\n"); 1274 _exit(exitval); 1275 } 1276 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1277 1278 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1279 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1280 1281 validate_status_stopped(status, sigval); 1282 1283 DPRINTF("Call GETDBREGS for the child process (r1)\n"); 1284 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1); 1285 1286 DPRINTF("State of the debug registers (r1):\n"); 1287 for (i = 0; i < __arraycount(r1.dr); i++) 1288 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]); 1289 1290 r1.dr[1] = (long)(intptr_t)check_happy; 1291 DPRINTF("Set DR1 (r1.dr[1]) to new value %" PRIxREGISTER "\n", 1292 r1.dr[1]); 1293 1294 r1.dr[7] = dr7.raw; 1295 DPRINTF("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n", 1296 r1.dr[7]); 1297 1298 DPRINTF("New state of the debug registers (r1):\n"); 1299 for (i = 0; i < __arraycount(r1.dr); i++) 1300 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]); 1301 1302 DPRINTF("Call SETDBREGS for the child process (r1)\n"); 1303 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1); 1304 1305 DPRINTF("Call CONTINUE for the child process\n"); 1306 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1307 1308 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1309 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1310 1311 validate_status_stopped(status, SIGTRAP); 1312 1313 DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 1314 SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 1315 1316 DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1317 DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 1318 info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1319 info.psi_siginfo.si_errno); 1320 1321 DPRINTF("Before checking siginfo_t\n"); 1322 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 1323 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_DBREG); 1324 1325 DPRINTF("Remove code trap from check_happy=%p\n", check_happy); 1326 dr7.bits.global_dr1_breakpoint = 0; 1327 r1.dr[7] = dr7.raw; 1328 DPRINTF("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n", 1329 r1.dr[7]); 1330 1331 DPRINTF("Call SETDBREGS for the child process (r1)\n"); 1332 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1); 1333 1334 DPRINTF("Call CONTINUE for the child process\n"); 1335 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1336 1337 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1338 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1339 1340 validate_status_stopped(status, sigval); 1341 1342 DPRINTF("Before resuming the child process where it left off and " 1343 "without signal to be sent\n"); 1344 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1345 1346 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1347 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1348 1349 validate_status_exited(status, exitval); 1350 1351 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1352 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 1353 } 1354 #endif 1355 1356 #if defined(HAVE_DBREGS) 1357 ATF_TC(dbregs_dr2_trap_code); 1358 ATF_TC_HEAD(dbregs_dr2_trap_code, tc) 1359 { 1360 atf_tc_set_md_var(tc, "descr", 1361 "Verify that setting trap with DR2 triggers SIGTRAP " 1362 "(break on code execution trap)"); 1363 } 1364 1365 ATF_TC_BODY(dbregs_dr2_trap_code, tc) 1366 { 1367 const int exitval = 5; 1368 const int sigval = SIGSTOP; 1369 pid_t child, wpid; 1370 #if defined(TWAIT_HAVE_STATUS) 1371 int status; 1372 #endif 1373 struct dbreg r1; 1374 size_t i; 1375 volatile int watchme = 1; 1376 union u dr7; 1377 1378 struct ptrace_siginfo info; 1379 memset(&info, 0, sizeof(info)); 1380 1381 if (!can_we_set_dbregs()) { 1382 atf_tc_skip("Either run this test as root or set sysctl(3) " 1383 "security.models.extensions.user_set_dbregs to 1"); 1384 } 1385 1386 dr7.raw = 0; 1387 dr7.bits.global_dr2_breakpoint = 1; 1388 dr7.bits.condition_dr2 = 0; /* 0b00 -- break on code execution */ 1389 dr7.bits.len_dr2 = 0; /* 0b00 -- 1 byte */ 1390 1391 DPRINTF("Before forking process PID=%d\n", getpid()); 1392 SYSCALL_REQUIRE((child = fork()) != -1); 1393 if (child == 0) { 1394 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1395 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1396 1397 DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1398 FORKEE_ASSERT(raise(sigval) == 0); 1399 1400 printf("check_happy(%d)=%d\n", watchme, check_happy(watchme)); 1401 1402 DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1403 FORKEE_ASSERT(raise(sigval) == 0); 1404 1405 DPRINTF("Before exiting of the child process\n"); 1406 _exit(exitval); 1407 } 1408 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1409 1410 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1411 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1412 1413 validate_status_stopped(status, sigval); 1414 1415 DPRINTF("Call GETDBREGS for the child process (r1)\n"); 1416 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1); 1417 1418 DPRINTF("State of the debug registers (r1):\n"); 1419 for (i = 0; i < __arraycount(r1.dr); i++) 1420 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]); 1421 1422 r1.dr[2] = (long)(intptr_t)check_happy; 1423 DPRINTF("Set DR2 (r1.dr[2]) to new value %" PRIxREGISTER "\n", 1424 r1.dr[2]); 1425 1426 r1.dr[7] = dr7.raw; 1427 DPRINTF("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n", 1428 r1.dr[7]); 1429 1430 DPRINTF("New state of the debug registers (r1):\n"); 1431 for (i = 0; i < __arraycount(r1.dr); i++) 1432 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]); 1433 1434 DPRINTF("Call SETDBREGS for the child process (r1)\n"); 1435 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1); 1436 1437 DPRINTF("Call CONTINUE for the child process\n"); 1438 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1439 1440 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1441 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1442 1443 validate_status_stopped(status, SIGTRAP); 1444 1445 DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 1446 SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 1447 1448 DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1449 DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 1450 info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1451 info.psi_siginfo.si_errno); 1452 1453 DPRINTF("Before checking siginfo_t\n"); 1454 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 1455 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_DBREG); 1456 1457 DPRINTF("Remove code trap from check_happy=%p\n", check_happy); 1458 dr7.bits.global_dr2_breakpoint = 0; 1459 r1.dr[7] = dr7.raw; 1460 DPRINTF("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n", 1461 r1.dr[7]); 1462 1463 DPRINTF("Call SETDBREGS for the child process (r1)\n"); 1464 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1); 1465 1466 DPRINTF("Call CONTINUE for the child process\n"); 1467 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1468 1469 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1470 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1471 1472 validate_status_stopped(status, sigval); 1473 1474 DPRINTF("Before resuming the child process where it left off and " 1475 "without signal to be sent\n"); 1476 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1477 1478 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1479 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1480 1481 validate_status_exited(status, exitval); 1482 1483 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1484 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 1485 } 1486 #endif 1487 1488 #if defined(HAVE_DBREGS) 1489 ATF_TC(dbregs_dr3_trap_code); 1490 ATF_TC_HEAD(dbregs_dr3_trap_code, tc) 1491 { 1492 atf_tc_set_md_var(tc, "descr", 1493 "Verify that setting trap with DR3 triggers SIGTRAP " 1494 "(break on code execution trap)"); 1495 } 1496 1497 ATF_TC_BODY(dbregs_dr3_trap_code, tc) 1498 { 1499 const int exitval = 5; 1500 const int sigval = SIGSTOP; 1501 pid_t child, wpid; 1502 #if defined(TWAIT_HAVE_STATUS) 1503 int status; 1504 #endif 1505 struct dbreg r1; 1506 size_t i; 1507 volatile int watchme = 1; 1508 union u dr7; 1509 1510 struct ptrace_siginfo info; 1511 memset(&info, 0, sizeof(info)); 1512 1513 if (!can_we_set_dbregs()) { 1514 atf_tc_skip("Either run this test as root or set sysctl(3) " 1515 "security.models.extensions.user_set_dbregs to 1"); 1516 } 1517 1518 dr7.raw = 0; 1519 dr7.bits.global_dr3_breakpoint = 1; 1520 dr7.bits.condition_dr3 = 0; /* 0b00 -- break on code execution */ 1521 dr7.bits.len_dr3 = 0; /* 0b00 -- 1 byte */ 1522 1523 DPRINTF("Before forking process PID=%d\n", getpid()); 1524 SYSCALL_REQUIRE((child = fork()) != -1); 1525 if (child == 0) { 1526 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1527 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1528 1529 DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1530 FORKEE_ASSERT(raise(sigval) == 0); 1531 1532 printf("check_happy(%d)=%d\n", watchme, check_happy(watchme)); 1533 1534 DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1535 FORKEE_ASSERT(raise(sigval) == 0); 1536 1537 DPRINTF("Before exiting of the child process\n"); 1538 _exit(exitval); 1539 } 1540 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1541 1542 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1543 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1544 1545 validate_status_stopped(status, sigval); 1546 1547 DPRINTF("Call GETDBREGS for the child process (r1)\n"); 1548 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1); 1549 1550 DPRINTF("State of the debug registers (r1):\n"); 1551 for (i = 0; i < __arraycount(r1.dr); i++) 1552 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]); 1553 1554 r1.dr[3] = (long)(intptr_t)check_happy; 1555 DPRINTF("Set DR3 (r1.dr[3]) to new value %" PRIxREGISTER "\n", 1556 r1.dr[3]); 1557 1558 r1.dr[7] = dr7.raw; 1559 DPRINTF("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n", 1560 r1.dr[7]); 1561 1562 DPRINTF("New state of the debug registers (r1):\n"); 1563 for (i = 0; i < __arraycount(r1.dr); i++) 1564 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]); 1565 1566 DPRINTF("Call SETDBREGS for the child process (r1)\n"); 1567 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1); 1568 1569 DPRINTF("Call CONTINUE for the child process\n"); 1570 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1571 1572 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1573 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1574 1575 validate_status_stopped(status, SIGTRAP); 1576 1577 DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 1578 SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 1579 1580 DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1581 DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 1582 info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1583 info.psi_siginfo.si_errno); 1584 1585 DPRINTF("Before checking siginfo_t\n"); 1586 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP); 1587 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_DBREG); 1588 1589 DPRINTF("Remove code trap from check_happy=%p\n", check_happy); 1590 dr7.bits.global_dr3_breakpoint = 0; 1591 r1.dr[7] = dr7.raw; 1592 DPRINTF("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n", 1593 r1.dr[7]); 1594 1595 DPRINTF("Call SETDBREGS for the child process (r1)\n"); 1596 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1); 1597 1598 DPRINTF("Call CONTINUE for the child process\n"); 1599 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1600 1601 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1602 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1603 1604 validate_status_stopped(status, sigval); 1605 1606 DPRINTF("Before resuming the child process where it left off and " 1607 "without signal to be sent\n"); 1608 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1609 1610 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1611 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1612 1613 validate_status_exited(status, exitval); 1614 1615 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1616 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 1617 } 1618 #endif 1619 1620 volatile lwpid_t x86_the_lwp_id = 0; 1621 1622 static void __used 1623 x86_lwp_main_func(void *arg) 1624 { 1625 x86_the_lwp_id = _lwp_self(); 1626 _lwp_exit(); 1627 } 1628 1629 static void 1630 dbregs_dont_inherit_lwp(int reg) 1631 { 1632 const int exitval = 5; 1633 const int sigval = SIGSTOP; 1634 pid_t child, wpid; 1635 #if defined(TWAIT_HAVE_STATUS) 1636 int status; 1637 #endif 1638 ptrace_state_t state; 1639 const int slen = sizeof(state); 1640 ptrace_event_t event; 1641 const int elen = sizeof(event); 1642 ucontext_t uc; 1643 lwpid_t lid; 1644 static const size_t ssize = 16*1024; 1645 void *stack; 1646 size_t i; 1647 struct dbreg r1; 1648 struct dbreg r2; 1649 1650 if (!can_we_set_dbregs()) { 1651 atf_tc_skip("Either run this test as root or set sysctl(3) " 1652 "security.models.extensions.user_set_dbregs to 1"); 1653 } 1654 1655 DPRINTF("Before forking process PID=%d\n", getpid()); 1656 SYSCALL_REQUIRE((child = fork()) != -1); 1657 if (child == 0) { 1658 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1659 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1660 1661 DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1662 FORKEE_ASSERT(raise(sigval) == 0); 1663 1664 DPRINTF("Before allocating memory for stack in child\n"); 1665 FORKEE_ASSERT((stack = malloc(ssize)) != NULL); 1666 1667 DPRINTF("Before making context for new lwp in child\n"); 1668 _lwp_makecontext(&uc, x86_lwp_main_func, NULL, NULL, stack, 1669 ssize); 1670 1671 DPRINTF("Before creating new in child\n"); 1672 FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0); 1673 1674 DPRINTF("Before waiting for lwp %d to exit\n", lid); 1675 FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0); 1676 1677 DPRINTF("Before verifying that reported %d and running lid %d " 1678 "are the same\n", lid, x86_the_lwp_id); 1679 FORKEE_ASSERT_EQ(lid, x86_the_lwp_id); 1680 1681 DPRINTF("Before exiting of the child process\n"); 1682 _exit(exitval); 1683 } 1684 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1685 1686 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1687 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1688 1689 validate_status_stopped(status, sigval); 1690 1691 DPRINTF("Set empty EVENT_MASK for the child %d\n", child); 1692 event.pe_set_event = PTRACE_LWP_CREATE; 1693 SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1); 1694 1695 DPRINTF("Call GETDBREGS for the child process (r1)\n"); 1696 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1); 1697 1698 DPRINTF("State of the debug registers (r1):\n"); 1699 for (i = 0; i < __arraycount(r1.dr); i++) 1700 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]); 1701 1702 r1.dr[reg] = (long)(intptr_t)check_happy; 1703 DPRINTF("Set DR%d (r1.dr[%d]) to new value %" PRIxREGISTER "\n", 1704 reg, reg, r1.dr[0]); 1705 1706 DPRINTF("New state of the debug registers (r1):\n"); 1707 for (i = 0; i < __arraycount(r1.dr); i++) 1708 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]); 1709 1710 DPRINTF("Call SETDBREGS for the child process (r1)\n"); 1711 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1); 1712 1713 DPRINTF("Before resuming the child process where it left off and " 1714 "without signal to be sent\n"); 1715 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1716 1717 DPRINTF("Before calling %s() for the child - expected stopped " 1718 "SIGTRAP\n", TWAIT_FNAME); 1719 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1720 1721 validate_status_stopped(status, SIGTRAP); 1722 1723 SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1); 1724 1725 ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE); 1726 1727 lid = state.pe_lwp; 1728 DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid); 1729 1730 DPRINTF("Call GETDBREGS for the child process new lwp (r2)\n"); 1731 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &r2, lid) != -1); 1732 1733 DPRINTF("State of the debug registers (r2):\n"); 1734 for (i = 0; i < __arraycount(r2.dr); i++) 1735 DPRINTF("r2[%zu]=%" PRIxREGISTER "\n", i, r2.dr[i]); 1736 1737 DPRINTF("Assert that (r1) and (r2) are not the same\n"); 1738 ATF_REQUIRE(memcmp(&r1, &r2, sizeof(r1)) != 0); 1739 1740 DPRINTF("Before resuming the child process where it left off and " 1741 "without signal to be sent\n"); 1742 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1743 1744 DPRINTF("Before calling %s() for the child - expected exited\n", 1745 TWAIT_FNAME); 1746 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1747 1748 validate_status_exited(status, exitval); 1749 1750 DPRINTF("Before calling %s() for the child - expected no process\n", 1751 TWAIT_FNAME); 1752 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 1753 } 1754 1755 ATF_TC(dbregs_dr0_dont_inherit_lwp); 1756 ATF_TC_HEAD(dbregs_dr0_dont_inherit_lwp, tc) 1757 { 1758 atf_tc_set_md_var(tc, "descr", 1759 "Verify that 1 LWP creation is intercepted by ptrace(2) with " 1760 "EVENT_MASK set to PTRACE_LWP_CREATE and Debug Register 0 from " 1761 "the forker thread is not inherited"); 1762 } 1763 1764 ATF_TC_BODY(dbregs_dr0_dont_inherit_lwp, tc) 1765 { 1766 dbregs_dont_inherit_lwp(0); 1767 } 1768 1769 ATF_TC(dbregs_dr1_dont_inherit_lwp); 1770 ATF_TC_HEAD(dbregs_dr1_dont_inherit_lwp, tc) 1771 { 1772 atf_tc_set_md_var(tc, "descr", 1773 "Verify that 1 LWP creation is intercepted by ptrace(2) with " 1774 "EVENT_MASK set to PTRACE_LWP_CREATE and Debug Register 1 from " 1775 "the forker thread is not inherited"); 1776 } 1777 1778 ATF_TC_BODY(dbregs_dr1_dont_inherit_lwp, tc) 1779 { 1780 dbregs_dont_inherit_lwp(1); 1781 } 1782 1783 ATF_TC(dbregs_dr2_dont_inherit_lwp); 1784 ATF_TC_HEAD(dbregs_dr2_dont_inherit_lwp, tc) 1785 { 1786 atf_tc_set_md_var(tc, "descr", 1787 "Verify that 1 LWP creation is intercepted by ptrace(2) with " 1788 "EVENT_MASK set to PTRACE_LWP_CREATE and Debug Register 2 from " 1789 "the forker thread is not inherited"); 1790 } 1791 1792 ATF_TC_BODY(dbregs_dr2_dont_inherit_lwp, tc) 1793 { 1794 dbregs_dont_inherit_lwp(2); 1795 } 1796 1797 ATF_TC(dbregs_dr3_dont_inherit_lwp); 1798 ATF_TC_HEAD(dbregs_dr3_dont_inherit_lwp, tc) 1799 { 1800 atf_tc_set_md_var(tc, "descr", 1801 "Verify that 1 LWP creation is intercepted by ptrace(2) with " 1802 "EVENT_MASK set to PTRACE_LWP_CREATE and Debug Register 3 from " 1803 "the forker thread is not inherited"); 1804 } 1805 1806 ATF_TC_BODY(dbregs_dr3_dont_inherit_lwp, tc) 1807 { 1808 dbregs_dont_inherit_lwp(3); 1809 } 1810 1811 static void 1812 dbregs_dont_inherit_execve(int reg) 1813 { 1814 const int sigval = SIGTRAP; 1815 pid_t child, wpid; 1816 #if defined(TWAIT_HAVE_STATUS) 1817 int status; 1818 #endif 1819 size_t i; 1820 struct dbreg r1; 1821 struct dbreg r2; 1822 1823 struct ptrace_siginfo info; 1824 memset(&info, 0, sizeof(info)); 1825 1826 if (!can_we_set_dbregs()) { 1827 atf_tc_skip("Either run this test as root or set sysctl(3) " 1828 "security.models.extensions.user_set_dbregs to 1"); 1829 } 1830 1831 DPRINTF("Before forking process PID=%d\n", getpid()); 1832 SYSCALL_REQUIRE((child = fork()) != -1); 1833 if (child == 0) { 1834 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 1835 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 1836 1837 DPRINTF("Before raising %s from child\n", strsignal(sigval)); 1838 FORKEE_ASSERT(raise(sigval) == 0); 1839 1840 DPRINTF("Before calling execve(2) from child\n"); 1841 execlp("/bin/echo", "/bin/echo", NULL); 1842 1843 FORKEE_ASSERT(0 && "Not reached"); 1844 } 1845 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 1846 1847 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1848 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1849 1850 validate_status_stopped(status, sigval); 1851 1852 DPRINTF("Call GETDBREGS for the child process (r1)\n"); 1853 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1); 1854 1855 DPRINTF("State of the debug registers (r1):\n"); 1856 for (i = 0; i < __arraycount(r1.dr); i++) 1857 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]); 1858 1859 r1.dr[reg] = (long)(intptr_t)check_happy; 1860 DPRINTF("Set DR%d (r1.dr[%d]) to new value %" PRIxREGISTER "\n", 1861 reg, reg, r1.dr[reg]); 1862 1863 DPRINTF("New state of the debug registers (r1):\n"); 1864 for (i = 0; i < __arraycount(r1.dr); i++) 1865 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]); 1866 1867 DPRINTF("Call SETDBREGS for the child process (r1)\n"); 1868 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1); 1869 1870 DPRINTF("Before resuming the child process where it left off and " 1871 "without signal to be sent\n"); 1872 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1873 1874 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1875 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1876 1877 validate_status_stopped(status, sigval); 1878 1879 DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n"); 1880 SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1); 1881 1882 DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid); 1883 DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n", 1884 info.psi_siginfo.si_signo, info.psi_siginfo.si_code, 1885 info.psi_siginfo.si_errno); 1886 1887 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval); 1888 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC); 1889 1890 DPRINTF("Call GETDBREGS for the child process after execve(2)\n"); 1891 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &r2, 0) != -1); 1892 1893 DPRINTF("State of the debug registers (r2):\n"); 1894 for (i = 0; i < __arraycount(r2.dr); i++) 1895 DPRINTF("r2[%zu]=%" PRIxREGISTER "\n", i, r2.dr[i]); 1896 1897 DPRINTF("Assert that (r1) and (r2) are not the same\n"); 1898 ATF_REQUIRE(memcmp(&r1, &r2, sizeof(r1)) != 0); 1899 1900 DPRINTF("Before resuming the child process where it left off and " 1901 "without signal to be sent\n"); 1902 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 1903 1904 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1905 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 1906 1907 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 1908 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 1909 } 1910 1911 ATF_TC(dbregs_dr0_dont_inherit_execve); 1912 ATF_TC_HEAD(dbregs_dr0_dont_inherit_execve, tc) 1913 { 1914 atf_tc_set_md_var(tc, "descr", 1915 "Verify that execve(2) is intercepted by tracer and Debug " 1916 "Register 0 is reset"); 1917 } 1918 1919 ATF_TC_BODY(dbregs_dr0_dont_inherit_execve, tc) 1920 { 1921 dbregs_dont_inherit_execve(0); 1922 } 1923 1924 ATF_TC(dbregs_dr1_dont_inherit_execve); 1925 ATF_TC_HEAD(dbregs_dr1_dont_inherit_execve, tc) 1926 { 1927 atf_tc_set_md_var(tc, "descr", 1928 "Verify that execve(2) is intercepted by tracer and Debug " 1929 "Register 1 is reset"); 1930 } 1931 1932 ATF_TC_BODY(dbregs_dr1_dont_inherit_execve, tc) 1933 { 1934 dbregs_dont_inherit_execve(1); 1935 } 1936 1937 ATF_TC(dbregs_dr2_dont_inherit_execve); 1938 ATF_TC_HEAD(dbregs_dr2_dont_inherit_execve, tc) 1939 { 1940 atf_tc_set_md_var(tc, "descr", 1941 "Verify that execve(2) is intercepted by tracer and Debug " 1942 "Register 2 is reset"); 1943 } 1944 1945 ATF_TC_BODY(dbregs_dr2_dont_inherit_execve, tc) 1946 { 1947 dbregs_dont_inherit_execve(2); 1948 } 1949 1950 ATF_TC(dbregs_dr3_dont_inherit_execve); 1951 ATF_TC_HEAD(dbregs_dr3_dont_inherit_execve, tc) 1952 { 1953 atf_tc_set_md_var(tc, "descr", 1954 "Verify that execve(2) is intercepted by tracer and Debug " 1955 "Register 3 is reset"); 1956 } 1957 1958 ATF_TC_BODY(dbregs_dr3_dont_inherit_execve, tc) 1959 { 1960 dbregs_dont_inherit_execve(3); 1961 } 1962 1963 /// ---------------------------------------------------------------------------- 1964 1965 ATF_TC(x86_cve_2018_8897); 1966 ATF_TC_HEAD(x86_cve_2018_8897, tc) 1967 { 1968 atf_tc_set_md_var(tc, "descr", 1969 "Verify mitigation for CVE-2018-8897 (POP SS debug exception)"); 1970 } 1971 1972 #define X86_CVE_2018_8897_PAGE 0x5000 /* page addressable by 32-bit registers */ 1973 1974 static void 1975 x86_cve_2018_8897_trigger(void) 1976 { 1977 /* 1978 * A function to trigger the POP SS (CVE-2018-8897) vulnerability 1979 * 1980 * ifdef __x86_64__ 1981 * 1982 * We need to switch to 32-bit mode execution on 64-bit kernel. 1983 * This is achieved with far jump instruction and GDT descriptor 1984 * set to 32-bit CS selector. The 32-bit CS selector is kernel 1985 * specific, in the NetBSD case registered as GUCODE32_SEL 1986 * that is equal to (14 (decimal) << 3) with GDT and user 1987 * privilege level (this makes it 0x73). 1988 * 1989 * In UNIX as(1) assembly x86_64 far jump is coded as ljmp. 1990 * amd64 ljmp requires an indirect address with cs:RIP. 1991 * 1992 * When we are running in 32-bit mode, it's similar to the 1993 * mode as if the binary had been launched in netbsd32. 1994 * 1995 * There are two versions of this exploit, one with RIP 1996 * relative code and the other with static addresses. 1997 * The first one is PIE code aware, the other no-PIE one. 1998 * 1999 * 2000 * After switching to the 32-bit mode we can move on to the remaining 2001 * part of the exploit. 2002 * 2003 * endif // __x86_64__ 2004 * 2005 * Set the stack pointer to the page we allocated earlier. Remember 2006 * that we put an SS selector exactly at this address, so we can pop. 2007 * 2008 * movl $0x5000,%esp 2009 * 2010 * Pop the SS selector off the stack. This reloads the SS selector, 2011 * which is fine. Remember that we set DR0 at address 0x5000, which 2012 * we are now reading. Therefore, on this instruction, the CPU will 2013 * raise a #DB exception. 2014 * 2015 * But the "pop %ss" instruction is special: it blocks exceptions 2016 * until the next instruction is executed. So the #DB that we just 2017 * raised is actually blocked. 2018 * 2019 * pop %ss 2020 * 2021 * We are still here, and didn't receive the #DB. After we execute 2022 * this instruction, the effect of "pop %ss" will disappear, and 2023 * we will receive the #DB for real. 2024 * 2025 * int $4 2026 * 2027 * Here the bug happens. We executed "int $4", so we entered the 2028 * kernel, with interrupts disabled. The #DB that was pending is 2029 * received. But, it is received immediately in kernel mode, and is 2030 * _NOT_ received when interrupts are enabled again. 2031 * 2032 * It means that, in the first instruction of the $4 handler, we 2033 * think we are safe with interrupts disabled. But we aren't, and 2034 * just got interrupted. 2035 * 2036 * The new interrupt handler doesn't handle this particular context: 2037 * we are entered in kernel mode, the previous context was kernel 2038 * mode too but it still had the user context loaded. 2039 * 2040 * We find ourselves not doing a 'swapgs'. At the end of the day, it 2041 * means that we call trap() with a curcpu() that is fully 2042 * controllable by userland. From then on, it is easy to escalate 2043 * privileges. 2044 * 2045 * With SVS it also means we don't switch CR3, so this results in a 2046 * triple fault, which this time cannot be turned to a privilege 2047 * escalation. 2048 */ 2049 2050 #if __x86_64__ 2051 #if __PIE__ 2052 void *csRIP; 2053 2054 csRIP = malloc(sizeof(int) + sizeof(short)); 2055 FORKEE_ASSERT(csRIP != NULL); 2056 2057 __asm__ __volatile__( 2058 " leal 24(%%eip), %%eax\n\t" 2059 " movq %0, %%rdx\n\t" 2060 " movl %%eax, (%%rdx)\n\t" 2061 " movw $0x73, 4(%%rdx)\n\t" 2062 " movq %1, %%rax\n\t" 2063 " ljmp *(%%rax)\n\t" 2064 " .code32\n\t" 2065 " movl $0x5000, %%esp\n\t" 2066 " pop %%ss\n\t" 2067 " int $4\n\t" 2068 " .code64\n\t" 2069 : "=m"(csRIP) 2070 : "m"(csRIP) 2071 : "%rax", "%rdx", "%rsp" 2072 ); 2073 #else /* !__PIE__ */ 2074 __asm__ __volatile__( 2075 " movq $farjmp32, %%rax\n\t" 2076 " ljmp *(%%rax)\n\t" 2077 "farjmp32:\n\t" 2078 " .long trigger32\n\t" 2079 " .word 0x73\n\t" 2080 " .code32\n\t" 2081 "trigger32:\n\t" 2082 " movl $0x5000, %%esp\n\t" 2083 " pop %%ss\n\t" 2084 " int $4\n\t" 2085 " .code64\n\t" 2086 : 2087 : 2088 : "%rax", "%rsp" 2089 ); 2090 #endif 2091 #elif __i386__ 2092 __asm__ __volatile__( 2093 "movl $0x5000, %%esp\n\t" 2094 "pop %%ss\n\t" 2095 "int $4\n\t" 2096 : 2097 : 2098 : "%esp" 2099 ); 2100 #endif 2101 } 2102 2103 ATF_TC_BODY(x86_cve_2018_8897, tc) 2104 { 2105 const int sigval = SIGSTOP; 2106 pid_t child, wpid; 2107 #if defined(TWAIT_HAVE_STATUS) 2108 int status; 2109 #endif 2110 char *trap_page; 2111 struct dbreg db; 2112 2113 2114 if (!can_we_set_dbregs()) { 2115 atf_tc_skip("Either run this test as root or set sysctl(3) " 2116 "security.models.extensions.user_set_dbregs to 1"); 2117 } 2118 2119 DPRINTF("Before forking process PID=%d\n", getpid()); 2120 SYSCALL_REQUIRE((child = fork()) != -1); 2121 if (child == 0) { 2122 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2123 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2124 2125 trap_page = mmap((void *)X86_CVE_2018_8897_PAGE, 2126 sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE, 2127 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0); 2128 2129 /* trigger page fault */ 2130 memset(trap_page, 0, sysconf(_SC_PAGESIZE)); 2131 2132 // kernel GDT 2133 #if __x86_64__ 2134 /* SS selector (descriptor 9 (0x4f >> 3)) */ 2135 *trap_page = 0x4f; 2136 #elif __i386__ 2137 /* SS selector (descriptor 4 (0x23 >> 3)) */ 2138 *trap_page = 0x23; 2139 #endif 2140 2141 DPRINTF("Before raising %s from child\n", strsignal(sigval)); 2142 FORKEE_ASSERT(raise(sigval) == 0); 2143 2144 x86_cve_2018_8897_trigger(); 2145 2146 /* NOTREACHED */ 2147 FORKEE_ASSERTX(0 && "This shall not be reached"); 2148 } 2149 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2150 2151 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2152 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2153 2154 validate_status_stopped(status, sigval); 2155 2156 DPRINTF("Call GETDBREGS for the child process\n"); 2157 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &db, 0) != -1); 2158 2159 /* 2160 * Set up the dbregs. We put the 0x5000 address in DR0. 2161 * It means that, the first time we touch this, the CPU will trigger a 2162 * #DB exception. 2163 */ 2164 db.dr[0] = X86_CVE_2018_8897_PAGE; 2165 db.dr[7] = 0x30003; 2166 2167 DPRINTF("Call SETDBREGS for the child process\n"); 2168 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &db, 0) != -1); 2169 2170 DPRINTF("Before resuming the child process where it left off and " 2171 "without signal to be sent\n"); 2172 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2173 2174 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2175 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2176 2177 // In this test we receive SIGFPE, is this appropriate? 2178 // validate_status_stopped(status, SIGFPE); 2179 2180 DPRINTF("Kill the child process\n"); 2181 SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1); 2182 2183 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2184 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2185 2186 validate_status_signaled(status, SIGKILL, 0); 2187 2188 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2189 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 2190 } 2191 2192 ATF_TC(x86_regs_mm_read); 2193 ATF_TC_HEAD(x86_regs_mm_read, tc) 2194 { 2195 atf_tc_set_md_var(tc, "descr", 2196 "Set MMX (mm0..mm7) reg values from debugged program and read " 2197 "them via PT_GETFPREGS, comparing values against expected."); 2198 } 2199 2200 __attribute__((target("mmx"))) 2201 static __inline void set_mm_regs(const uint64_t mm[]) 2202 { 2203 __asm__ __volatile__( 2204 "movq 0x00(%0), %%mm0\n\t" 2205 "movq 0x08(%0), %%mm1\n\t" 2206 "movq 0x10(%0), %%mm2\n\t" 2207 "movq 0x18(%0), %%mm3\n\t" 2208 "movq 0x20(%0), %%mm4\n\t" 2209 "movq 0x28(%0), %%mm5\n\t" 2210 "movq 0x30(%0), %%mm6\n\t" 2211 "movq 0x38(%0), %%mm7\n\t" 2212 "int3\n\t" 2213 : 2214 : "b"(mm) 2215 : "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" 2216 ); 2217 } 2218 2219 ATF_TC_BODY(x86_regs_mm_read, tc) 2220 { 2221 const int exitval = 5; 2222 pid_t child, wpid; 2223 #if defined(TWAIT_HAVE_STATUS) 2224 const int sigval = SIGTRAP; 2225 int status; 2226 #endif 2227 struct fpreg fpr; 2228 2229 const uint64_t mm[] = { 2230 0x0001020304050607, 2231 0x1011121314151617, 2232 0x2021222324252627, 2233 0x3031323334353637, 2234 0x4041424344454647, 2235 0x5051525354555657, 2236 0x6061626364656667, 2237 0x7071727374757677, 2238 }; 2239 2240 /* verify whether MMX is supported here */ 2241 DPRINTF("Before invoking cpuid\n"); 2242 { 2243 unsigned int eax, ebx, ecx, edx; 2244 if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx)) 2245 atf_tc_skip("CPUID is not supported by the CPU"); 2246 2247 DPRINTF("cpuid: EDX = %08x\n", edx); 2248 2249 if (!(edx & bit_MMX)) 2250 atf_tc_skip("MMX is not supported by the CPU"); 2251 } 2252 2253 DPRINTF("Before forking process PID=%d\n", getpid()); 2254 SYSCALL_REQUIRE((child = fork()) != -1); 2255 if (child == 0) { 2256 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2257 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2258 2259 DPRINTF("Before running assembly from child\n"); 2260 set_mm_regs(mm); 2261 2262 DPRINTF("Before exiting of the child process\n"); 2263 _exit(exitval); 2264 } 2265 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2266 2267 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2268 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2269 2270 validate_status_stopped(status, sigval); 2271 2272 DPRINTF("Call GETFPREGS for the child process\n"); 2273 SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1); 2274 2275 #if defined(__x86_64__) 2276 #define MM_REG(n) fpr.fxstate.fx_87_ac[n].r.f87_mantissa 2277 #else 2278 #define MM_REG(n) fpr.fstate.s87_ac[n].f87_mantissa 2279 #endif 2280 2281 ATF_CHECK_EQ(MM_REG(0), mm[0]); 2282 ATF_CHECK_EQ(MM_REG(1), mm[1]); 2283 ATF_CHECK_EQ(MM_REG(2), mm[2]); 2284 ATF_CHECK_EQ(MM_REG(3), mm[3]); 2285 ATF_CHECK_EQ(MM_REG(4), mm[4]); 2286 ATF_CHECK_EQ(MM_REG(5), mm[5]); 2287 ATF_CHECK_EQ(MM_REG(6), mm[6]); 2288 ATF_CHECK_EQ(MM_REG(7), mm[7]); 2289 2290 #undef MM_REG 2291 2292 DPRINTF("Before resuming the child process where it left off and " 2293 "without signal to be sent\n"); 2294 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2295 2296 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2297 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2298 2299 validate_status_exited(status, exitval); 2300 2301 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2302 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 2303 } 2304 2305 __attribute__((target("mmx"))) 2306 static __inline void get_mm_regs(uint64_t v_mm[]) 2307 { 2308 const uint64_t fill = 0x0F0F0F0F0F0F0F0F; 2309 2310 __asm__ __volatile__( 2311 /* fill registers with clobber pattern */ 2312 "movq %1, %%mm0\n\t" 2313 "movq %1, %%mm1\n\t" 2314 "movq %1, %%mm2\n\t" 2315 "movq %1, %%mm3\n\t" 2316 "movq %1, %%mm4\n\t" 2317 "movq %1, %%mm5\n\t" 2318 "movq %1, %%mm6\n\t" 2319 "movq %1, %%mm7\n\t" 2320 "\n\t" 2321 "int3\n\t" 2322 "\n\t" 2323 "movq %%mm0, 0x00(%0)\n\t" 2324 "movq %%mm1, 0x08(%0)\n\t" 2325 "movq %%mm2, 0x10(%0)\n\t" 2326 "movq %%mm3, 0x18(%0)\n\t" 2327 "movq %%mm4, 0x20(%0)\n\t" 2328 "movq %%mm5, 0x28(%0)\n\t" 2329 "movq %%mm6, 0x30(%0)\n\t" 2330 "movq %%mm7, 0x38(%0)\n\t" 2331 : 2332 : "a"(v_mm), "m"(fill) 2333 : "%mm0", "%mm1", "%mm2", "%mm3", "%mm4", "%mm5", "%mm6", "%mm7" 2334 ); 2335 } 2336 2337 ATF_TC(x86_regs_mm_write); 2338 ATF_TC_HEAD(x86_regs_mm_write, tc) 2339 { 2340 atf_tc_set_md_var(tc, "descr", 2341 "Set mm0..mm7 reg values into a debugged program via " 2342 "PT_SETFPREGS and compare the result against expected."); 2343 } 2344 2345 ATF_TC_BODY(x86_regs_mm_write, tc) 2346 { 2347 const int exitval = 5; 2348 pid_t child, wpid; 2349 #if defined(TWAIT_HAVE_STATUS) 2350 const int sigval = SIGTRAP; 2351 int status; 2352 #endif 2353 struct fpreg fpr; 2354 2355 const uint64_t mm[] = { 2356 0x0001020304050607, 2357 0x1011121314151617, 2358 0x2021222324252627, 2359 0x3031323334353637, 2360 0x4041424344454647, 2361 0x5051525354555657, 2362 0x6061626364656667, 2363 0x7071727374757677, 2364 }; 2365 2366 /* verify whether MMX is supported here */ 2367 DPRINTF("Before invoking cpuid\n"); 2368 { 2369 unsigned int eax, ebx, ecx, edx; 2370 if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx)) 2371 atf_tc_skip("CPUID is not supported by the CPU"); 2372 2373 DPRINTF("cpuid: EDX = %08x\n", edx); 2374 2375 if (!(edx & bit_MMX)) 2376 atf_tc_skip("MMX is not supported by the CPU"); 2377 } 2378 2379 DPRINTF("Before forking process PID=%d\n", getpid()); 2380 SYSCALL_REQUIRE((child = fork()) != -1); 2381 if (child == 0) { 2382 uint64_t v_mm[8]; 2383 2384 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2385 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2386 2387 DPRINTF("Before running assembly from child\n"); 2388 get_mm_regs(v_mm); 2389 2390 DPRINTF("Before comparing results\n"); 2391 FORKEE_ASSERT_EQ(v_mm[0], mm[0]); 2392 FORKEE_ASSERT_EQ(v_mm[1], mm[1]); 2393 FORKEE_ASSERT_EQ(v_mm[2], mm[2]); 2394 FORKEE_ASSERT_EQ(v_mm[3], mm[3]); 2395 FORKEE_ASSERT_EQ(v_mm[4], mm[4]); 2396 FORKEE_ASSERT_EQ(v_mm[5], mm[5]); 2397 FORKEE_ASSERT_EQ(v_mm[6], mm[6]); 2398 FORKEE_ASSERT_EQ(v_mm[7], mm[7]); 2399 2400 DPRINTF("Before exiting of the child process\n"); 2401 _exit(exitval); 2402 } 2403 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2404 2405 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2406 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2407 2408 validate_status_stopped(status, sigval); 2409 2410 DPRINTF("Call GETFPREGS for the child process\n"); 2411 SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1); 2412 2413 #if defined(__x86_64__) 2414 #define MM_REG(n) fpr.fxstate.fx_87_ac[n].r.f87_mantissa 2415 #else 2416 #define MM_REG(n) fpr.fstate.s87_ac[n].f87_mantissa 2417 #endif 2418 2419 MM_REG(0) = mm[0]; 2420 MM_REG(1) = mm[1]; 2421 MM_REG(2) = mm[2]; 2422 MM_REG(3) = mm[3]; 2423 MM_REG(4) = mm[4]; 2424 MM_REG(5) = mm[5]; 2425 MM_REG(6) = mm[6]; 2426 MM_REG(7) = mm[7]; 2427 2428 #undef MM_REG 2429 2430 DPRINTF("Call SETFPREGS for the child process\n"); 2431 SYSCALL_REQUIRE(ptrace(PT_SETFPREGS, child, &fpr, 0) != -1); 2432 2433 DPRINTF("Before resuming the child process where it left off and " 2434 "without signal to be sent\n"); 2435 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2436 2437 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2438 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2439 2440 validate_status_exited(status, exitval); 2441 2442 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2443 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 2444 } 2445 2446 __attribute__((target("sse"))) 2447 static __inline void set_xmm_regs(const void* xmm) 2448 { 2449 __asm__ __volatile__( 2450 "movaps 0x00(%0), %%xmm0\n\t" 2451 "movaps 0x10(%0), %%xmm1\n\t" 2452 "movaps 0x20(%0), %%xmm2\n\t" 2453 "movaps 0x30(%0), %%xmm3\n\t" 2454 "movaps 0x40(%0), %%xmm4\n\t" 2455 "movaps 0x50(%0), %%xmm5\n\t" 2456 "movaps 0x60(%0), %%xmm6\n\t" 2457 "movaps 0x70(%0), %%xmm7\n\t" 2458 #if defined(__x86_64__) 2459 "movaps 0x80(%0), %%xmm8\n\t" 2460 "movaps 0x90(%0), %%xmm9\n\t" 2461 "movaps 0xA0(%0), %%xmm10\n\t" 2462 "movaps 0xB0(%0), %%xmm11\n\t" 2463 "movaps 0xC0(%0), %%xmm12\n\t" 2464 "movaps 0xD0(%0), %%xmm13\n\t" 2465 "movaps 0xE0(%0), %%xmm14\n\t" 2466 "movaps 0xF0(%0), %%xmm15\n\t" 2467 #endif 2468 "int3\n\t" 2469 : 2470 : "b"(xmm) 2471 : "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", 2472 "%xmm7" 2473 #if defined(__x86_64__) 2474 , "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", 2475 "%xmm14", "%xmm15" 2476 #endif 2477 ); 2478 } 2479 2480 ATF_TC(x86_regs_xmm_read); 2481 ATF_TC_HEAD(x86_regs_xmm_read, tc) 2482 { 2483 atf_tc_set_md_var(tc, "descr", 2484 "Set xmm0..xmm15 (..xmm7 on i386) reg values from debugged program " 2485 "and read them via PT_GETFPREGS (PT_GETXMMREGS on i386), comparing " 2486 "values against expected."); 2487 } 2488 2489 ATF_TC_BODY(x86_regs_xmm_read, tc) 2490 { 2491 const int exitval = 5; 2492 pid_t child, wpid; 2493 #if defined(TWAIT_HAVE_STATUS) 2494 const int sigval = SIGTRAP; 2495 int status; 2496 #endif 2497 #if defined(__x86_64__) 2498 struct fpreg fpr; 2499 #else 2500 struct xmmregs fpr; 2501 #endif 2502 2503 const struct { 2504 uint64_t a, b; 2505 } xmm[] __aligned(16) = { 2506 { 0x0706050403020100, 0x0F0E0D0C0B0A0908, }, 2507 { 0x0807060504030201, 0x100F0E0D0C0B0A09, }, 2508 { 0x0908070605040302, 0x11100F0E0D0C0B0A, }, 2509 { 0x0A09080706050403, 0x1211100F0E0D0C0B, }, 2510 { 0x0B0A090807060504, 0x131211100F0E0D0C, }, 2511 { 0x0C0B0A0908070605, 0x14131211100F0E0D, }, 2512 { 0x0D0C0B0A09080706, 0x1514131211100F0E, }, 2513 { 0x0E0D0C0B0A090807, 0x161514131211100F, }, 2514 #if defined(__x86_64__) 2515 { 0x0F0E0D0C0B0A0908, 0x1716151413121110, }, 2516 { 0x100F0E0D0C0B0A09, 0x1817161514131211, }, 2517 { 0x11100F0E0D0C0B0A, 0x1918171615141312, }, 2518 { 0x1211100F0E0D0C0B, 0x1A19181716151413, }, 2519 { 0x131211100F0E0D0C, 0x1B1A191817161514, }, 2520 { 0x14131211100F0E0D, 0x1C1B1A1918171615, }, 2521 { 0x1514131211100F0E, 0x1D1C1B1A19181716, }, 2522 { 0x161514131211100F, 0x1E1D1C1B1A191817, }, 2523 #endif 2524 }; 2525 2526 /* verify whether SSE is supported here */ 2527 DPRINTF("Before invoking cpuid\n"); 2528 { 2529 unsigned int eax, ebx, ecx, edx; 2530 if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx)) 2531 atf_tc_skip("CPUID is not supported by the CPU"); 2532 2533 DPRINTF("cpuid: EDX = %08x\n", edx); 2534 2535 if (!(edx & bit_SSE)) 2536 atf_tc_skip("SSE is not supported by the CPU"); 2537 } 2538 2539 DPRINTF("Before forking process PID=%d\n", getpid()); 2540 SYSCALL_REQUIRE((child = fork()) != -1); 2541 if (child == 0) { 2542 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2543 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2544 2545 DPRINTF("Before running assembly from child\n"); 2546 set_xmm_regs(xmm); 2547 2548 DPRINTF("Before exiting of the child process\n"); 2549 _exit(exitval); 2550 } 2551 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2552 2553 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2554 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2555 2556 validate_status_stopped(status, sigval); 2557 2558 #if defined(__x86_64__) 2559 DPRINTF("Call GETFPREGS for the child process\n"); 2560 SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1); 2561 #else 2562 DPRINTF("Call GETXMMREGS for the child process\n"); 2563 SYSCALL_REQUIRE(ptrace(PT_GETXMMREGS, child, &fpr, 0) != -1); 2564 #endif 2565 2566 ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[0], &xmm[0], sizeof(*xmm))); 2567 ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[1], &xmm[1], sizeof(*xmm))); 2568 ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[2], &xmm[2], sizeof(*xmm))); 2569 ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[3], &xmm[3], sizeof(*xmm))); 2570 ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[4], &xmm[4], sizeof(*xmm))); 2571 ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[5], &xmm[5], sizeof(*xmm))); 2572 ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[6], &xmm[6], sizeof(*xmm))); 2573 ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[7], &xmm[7], sizeof(*xmm))); 2574 #if defined(__x86_64__) 2575 ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[8], &xmm[8], sizeof(*xmm))); 2576 ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[9], &xmm[9], sizeof(*xmm))); 2577 ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[10], &xmm[10], sizeof(*xmm))); 2578 ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[11], &xmm[11], sizeof(*xmm))); 2579 ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[12], &xmm[12], sizeof(*xmm))); 2580 ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[13], &xmm[13], sizeof(*xmm))); 2581 ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[14], &xmm[14], sizeof(*xmm))); 2582 ATF_CHECK(!memcmp(&fpr.fxstate.fx_xmm[15], &xmm[15], sizeof(*xmm))); 2583 #endif 2584 2585 DPRINTF("Before resuming the child process where it left off and " 2586 "without signal to be sent\n"); 2587 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2588 2589 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2590 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2591 2592 validate_status_exited(status, exitval); 2593 2594 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2595 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 2596 } 2597 2598 __attribute__((target("sse"))) 2599 static __inline void get_xmm_regs(void* v_xmm) 2600 { 2601 const struct { 2602 uint64_t a, b; 2603 } fill = {0x0F0F0F0F0F0F0F0F, 0x0F0F0F0F0F0F0F0F}; 2604 2605 __asm__ __volatile__( 2606 /* fill registers with clobber pattern */ 2607 "movaps %1, %%xmm0\n\t" 2608 "movaps %1, %%xmm1\n\t" 2609 "movaps %1, %%xmm2\n\t" 2610 "movaps %1, %%xmm3\n\t" 2611 "movaps %1, %%xmm4\n\t" 2612 "movaps %1, %%xmm5\n\t" 2613 "movaps %1, %%xmm6\n\t" 2614 "movaps %1, %%xmm7\n\t" 2615 #if defined(__x86_64__) 2616 "movaps %1, %%xmm8\n\t" 2617 "movaps %1, %%xmm9\n\t" 2618 "movaps %1, %%xmm10\n\t" 2619 "movaps %1, %%xmm11\n\t" 2620 "movaps %1, %%xmm12\n\t" 2621 "movaps %1, %%xmm13\n\t" 2622 "movaps %1, %%xmm14\n\t" 2623 "movaps %1, %%xmm15\n\t" 2624 #endif 2625 "\n\t" 2626 "int3\n\t" 2627 "\n\t" 2628 "movaps %%xmm0, 0x00(%0)\n\t" 2629 "movaps %%xmm1, 0x10(%0)\n\t" 2630 "movaps %%xmm2, 0x20(%0)\n\t" 2631 "movaps %%xmm3, 0x30(%0)\n\t" 2632 "movaps %%xmm4, 0x40(%0)\n\t" 2633 "movaps %%xmm5, 0x50(%0)\n\t" 2634 "movaps %%xmm6, 0x60(%0)\n\t" 2635 "movaps %%xmm7, 0x70(%0)\n\t" 2636 #if defined(__x86_64__) 2637 "movaps %%xmm8, 0x80(%0)\n\t" 2638 "movaps %%xmm9, 0x90(%0)\n\t" 2639 "movaps %%xmm10, 0xA0(%0)\n\t" 2640 "movaps %%xmm11, 0xB0(%0)\n\t" 2641 "movaps %%xmm12, 0xC0(%0)\n\t" 2642 "movaps %%xmm13, 0xD0(%0)\n\t" 2643 "movaps %%xmm14, 0xE0(%0)\n\t" 2644 "movaps %%xmm15, 0xF0(%0)\n\t" 2645 #endif 2646 : 2647 : "a"(v_xmm), "m"(fill) 2648 : "%xmm0", "%xmm1", "%xmm2", "%xmm3", "%xmm4", "%xmm5", "%xmm6", "%xmm7" 2649 #if defined(__x86_64__) 2650 , "%xmm8", "%xmm9", "%xmm10", "%xmm11", "%xmm12", "%xmm13", "%xmm14", 2651 "%xmm15" 2652 #endif 2653 ); 2654 } 2655 2656 ATF_TC(x86_regs_xmm_write); 2657 ATF_TC_HEAD(x86_regs_xmm_write, tc) 2658 { 2659 atf_tc_set_md_var(tc, "descr", 2660 "Set xmm0..xmm15 (..xmm7 on i386) reg values into a debugged " 2661 "program via PT_SETFPREGS (PT_SETXMMREGS on i386) and compare " 2662 "the result against expected."); 2663 } 2664 2665 ATF_TC_BODY(x86_regs_xmm_write, tc) 2666 { 2667 const int exitval = 5; 2668 pid_t child, wpid; 2669 #if defined(TWAIT_HAVE_STATUS) 2670 const int sigval = SIGTRAP; 2671 int status; 2672 #endif 2673 #if defined(__x86_64__) 2674 struct fpreg fpr; 2675 #else 2676 struct xmmregs fpr; 2677 #endif 2678 2679 const struct { 2680 uint64_t a, b; 2681 } xmm[] __aligned(16) = { 2682 { 0x0706050403020100, 0x0F0E0D0C0B0A0908, }, 2683 { 0x0807060504030201, 0x100F0E0D0C0B0A09, }, 2684 { 0x0908070605040302, 0x11100F0E0D0C0B0A, }, 2685 { 0x0A09080706050403, 0x1211100F0E0D0C0B, }, 2686 { 0x0B0A090807060504, 0x131211100F0E0D0C, }, 2687 { 0x0C0B0A0908070605, 0x14131211100F0E0D, }, 2688 { 0x0D0C0B0A09080706, 0x1514131211100F0E, }, 2689 { 0x0E0D0C0B0A090807, 0x161514131211100F, }, 2690 #if defined(__x86_64__) 2691 { 0x0F0E0D0C0B0A0908, 0x1716151413121110, }, 2692 { 0x100F0E0D0C0B0A09, 0x1817161514131211, }, 2693 { 0x11100F0E0D0C0B0A, 0x1918171615141312, }, 2694 { 0x1211100F0E0D0C0B, 0x1A19181716151413, }, 2695 { 0x131211100F0E0D0C, 0x1B1A191817161514, }, 2696 { 0x14131211100F0E0D, 0x1C1B1A1918171615, }, 2697 { 0x1514131211100F0E, 0x1D1C1B1A19181716, }, 2698 { 0x161514131211100F, 0x1E1D1C1B1A191817, }, 2699 #endif 2700 }; 2701 2702 /* verify whether SSE is supported here */ 2703 DPRINTF("Before invoking cpuid\n"); 2704 { 2705 unsigned int eax, ebx, ecx, edx; 2706 if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx)) 2707 atf_tc_skip("CPUID is not supported by the CPU"); 2708 2709 DPRINTF("cpuid: EDX = %08x\n", edx); 2710 2711 if (!(edx & bit_SSE)) 2712 atf_tc_skip("SSE is not supported by the CPU"); 2713 } 2714 2715 DPRINTF("Before forking process PID=%d\n", getpid()); 2716 SYSCALL_REQUIRE((child = fork()) != -1); 2717 if (child == 0) { 2718 struct { 2719 uint64_t a, b; 2720 } v_xmm[16] __aligned(16); 2721 2722 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid()); 2723 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 2724 2725 DPRINTF("Before running assembly from child\n"); 2726 get_xmm_regs(v_xmm); 2727 2728 DPRINTF("Before comparing results\n"); 2729 FORKEE_ASSERT(!memcmp(&v_xmm[0], &xmm[0], sizeof(*xmm))); 2730 FORKEE_ASSERT(!memcmp(&v_xmm[1], &xmm[1], sizeof(*xmm))); 2731 FORKEE_ASSERT(!memcmp(&v_xmm[2], &xmm[2], sizeof(*xmm))); 2732 FORKEE_ASSERT(!memcmp(&v_xmm[3], &xmm[3], sizeof(*xmm))); 2733 FORKEE_ASSERT(!memcmp(&v_xmm[4], &xmm[4], sizeof(*xmm))); 2734 FORKEE_ASSERT(!memcmp(&v_xmm[5], &xmm[5], sizeof(*xmm))); 2735 FORKEE_ASSERT(!memcmp(&v_xmm[6], &xmm[6], sizeof(*xmm))); 2736 FORKEE_ASSERT(!memcmp(&v_xmm[7], &xmm[7], sizeof(*xmm))); 2737 #if defined(__x86_64__) 2738 FORKEE_ASSERT(!memcmp(&v_xmm[8], &xmm[8], sizeof(*xmm))); 2739 FORKEE_ASSERT(!memcmp(&v_xmm[9], &xmm[9], sizeof(*xmm))); 2740 FORKEE_ASSERT(!memcmp(&v_xmm[10], &xmm[10], sizeof(*xmm))); 2741 FORKEE_ASSERT(!memcmp(&v_xmm[11], &xmm[11], sizeof(*xmm))); 2742 FORKEE_ASSERT(!memcmp(&v_xmm[12], &xmm[12], sizeof(*xmm))); 2743 FORKEE_ASSERT(!memcmp(&v_xmm[13], &xmm[13], sizeof(*xmm))); 2744 FORKEE_ASSERT(!memcmp(&v_xmm[14], &xmm[14], sizeof(*xmm))); 2745 FORKEE_ASSERT(!memcmp(&v_xmm[15], &xmm[15], sizeof(*xmm))); 2746 #endif 2747 2748 DPRINTF("Before exiting of the child process\n"); 2749 _exit(exitval); 2750 } 2751 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child); 2752 2753 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2754 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2755 2756 validate_status_stopped(status, sigval); 2757 2758 #if defined(__x86_64__) 2759 DPRINTF("Call GETFPREGS for the child process\n"); 2760 SYSCALL_REQUIRE(ptrace(PT_GETFPREGS, child, &fpr, 0) != -1); 2761 #else 2762 DPRINTF("Call GETXMMREGS for the child process\n"); 2763 SYSCALL_REQUIRE(ptrace(PT_GETXMMREGS, child, &fpr, 0) != -1); 2764 #endif 2765 2766 memcpy(&fpr.fxstate.fx_xmm[0], &xmm[0], sizeof(*xmm)); 2767 memcpy(&fpr.fxstate.fx_xmm[1], &xmm[1], sizeof(*xmm)); 2768 memcpy(&fpr.fxstate.fx_xmm[2], &xmm[2], sizeof(*xmm)); 2769 memcpy(&fpr.fxstate.fx_xmm[3], &xmm[3], sizeof(*xmm)); 2770 memcpy(&fpr.fxstate.fx_xmm[4], &xmm[4], sizeof(*xmm)); 2771 memcpy(&fpr.fxstate.fx_xmm[5], &xmm[5], sizeof(*xmm)); 2772 memcpy(&fpr.fxstate.fx_xmm[6], &xmm[6], sizeof(*xmm)); 2773 memcpy(&fpr.fxstate.fx_xmm[7], &xmm[7], sizeof(*xmm)); 2774 #if defined(__x86_64__) 2775 memcpy(&fpr.fxstate.fx_xmm[8], &xmm[8], sizeof(*xmm)); 2776 memcpy(&fpr.fxstate.fx_xmm[9], &xmm[9], sizeof(*xmm)); 2777 memcpy(&fpr.fxstate.fx_xmm[10], &xmm[10], sizeof(*xmm)); 2778 memcpy(&fpr.fxstate.fx_xmm[11], &xmm[11], sizeof(*xmm)); 2779 memcpy(&fpr.fxstate.fx_xmm[12], &xmm[12], sizeof(*xmm)); 2780 memcpy(&fpr.fxstate.fx_xmm[13], &xmm[13], sizeof(*xmm)); 2781 memcpy(&fpr.fxstate.fx_xmm[14], &xmm[14], sizeof(*xmm)); 2782 memcpy(&fpr.fxstate.fx_xmm[15], &xmm[15], sizeof(*xmm)); 2783 #endif 2784 2785 #if defined(__x86_64__) 2786 DPRINTF("Call SETFPREGS for the child process\n"); 2787 SYSCALL_REQUIRE(ptrace(PT_SETFPREGS, child, &fpr, 0) != -1); 2788 #else 2789 DPRINTF("Call SETXMMREGS for the child process\n"); 2790 SYSCALL_REQUIRE(ptrace(PT_SETXMMREGS, child, &fpr, 0) != -1); 2791 #endif 2792 2793 DPRINTF("Before resuming the child process where it left off and " 2794 "without signal to be sent\n"); 2795 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1); 2796 2797 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2798 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child); 2799 2800 validate_status_exited(status, exitval); 2801 2802 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME); 2803 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0)); 2804 } 2805 /// ---------------------------------------------------------------------------- 2806 2807 #define ATF_TP_ADD_TCS_PTRACE_WAIT_X86() \ 2808 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_print); \ 2809 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr0); \ 2810 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr1); \ 2811 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr2); \ 2812 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr3); \ 2813 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr0_yield); \ 2814 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr1_yield); \ 2815 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr2_yield); \ 2816 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr3_yield); \ 2817 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr0_continued); \ 2818 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr1_continued); \ 2819 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr2_continued); \ 2820 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr3_continued); \ 2821 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_writeonly_byte); \ 2822 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_writeonly_byte); \ 2823 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_writeonly_byte); \ 2824 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_writeonly_byte); \ 2825 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_writeonly_2bytes); \ 2826 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_writeonly_2bytes); \ 2827 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_writeonly_2bytes); \ 2828 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_writeonly_2bytes); \ 2829 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_writeonly_4bytes); \ 2830 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_writeonly_4bytes); \ 2831 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_writeonly_4bytes); \ 2832 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_writeonly_4bytes); \ 2833 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_readwrite_write_byte); \ 2834 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_readwrite_write_byte); \ 2835 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_readwrite_write_byte); \ 2836 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_readwrite_write_byte); \ 2837 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_readwrite_write_2bytes); \ 2838 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_readwrite_write_2bytes); \ 2839 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_readwrite_write_2bytes); \ 2840 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_readwrite_write_2bytes); \ 2841 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_readwrite_write_4bytes); \ 2842 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_readwrite_write_4bytes); \ 2843 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_readwrite_write_4bytes); \ 2844 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_readwrite_write_4bytes); \ 2845 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_readwrite_read_byte); \ 2846 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_readwrite_read_byte); \ 2847 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_readwrite_read_byte); \ 2848 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_readwrite_read_byte); \ 2849 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_readwrite_read_2bytes); \ 2850 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_readwrite_read_2bytes); \ 2851 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_readwrite_read_2bytes); \ 2852 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_readwrite_read_2bytes); \ 2853 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_readwrite_read_4bytes); \ 2854 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_readwrite_read_4bytes); \ 2855 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_readwrite_read_4bytes); \ 2856 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_readwrite_read_4bytes); \ 2857 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_code); \ 2858 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_code); \ 2859 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_code); \ 2860 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_code); \ 2861 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_dont_inherit_lwp); \ 2862 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_dont_inherit_lwp); \ 2863 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_dont_inherit_lwp); \ 2864 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_dont_inherit_lwp); \ 2865 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_dont_inherit_execve); \ 2866 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_dont_inherit_execve); \ 2867 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_dont_inherit_execve); \ 2868 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_dont_inherit_execve); \ 2869 ATF_TP_ADD_TC_HAVE_DBREGS(tp, x86_cve_2018_8897); \ 2870 ATF_TP_ADD_TC_HAVE_FPREGS(tp, x86_regs_mm_read); \ 2871 ATF_TP_ADD_TC_HAVE_FPREGS(tp, x86_regs_mm_write); \ 2872 ATF_TP_ADD_TC_HAVE_FPREGS(tp, x86_regs_xmm_read); \ 2873 ATF_TP_ADD_TC_HAVE_FPREGS(tp, x86_regs_xmm_write); 2874 #else 2875 #define ATF_TP_ADD_TCS_PTRACE_WAIT_X86() 2876 #endif 2877