t_ptrace_x86_wait.h revision 1.7 1 /* $NetBSD: t_ptrace_x86_wait.h,v 1.7 2018/05/26 20:27:48 kamil Exp $ */
2
3 /*-
4 * Copyright (c) 2016 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 case 1:
409 dr7.bits.global_dr1_breakpoint = 1;
410 dr7.bits.condition_dr1 = cond;
411 dr7.bits.len_dr1 = len;
412 case 2:
413 dr7.bits.global_dr2_breakpoint = 1;
414 dr7.bits.condition_dr2 = cond;
415 dr7.bits.len_dr2 = len;
416 case 3:
417 dr7.bits.global_dr3_breakpoint = 1;
418 dr7.bits.condition_dr3 = cond;
419 dr7.bits.len_dr3 = len;
420 break;
421 }
422
423 DPRINTF("Before forking process PID=%d\n", getpid());
424 SYSCALL_REQUIRE((child = fork()) != -1);
425 if (child == 0) {
426 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
427 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
428
429 DPRINTF("Before raising %s from child\n", strsignal(sigval));
430 FORKEE_ASSERT(raise(sigval) == 0);
431
432 if (write)
433 watchme = 1;
434 else
435 printf("watchme=%d\n", watchme);
436
437 DPRINTF("Before raising %s from child\n", strsignal(sigval));
438 FORKEE_ASSERT(raise(sigval) == 0);
439
440 DPRINTF("Before exiting of the child process\n");
441 _exit(exitval);
442 }
443 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
444
445 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
446 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
447
448 validate_status_stopped(status, sigval);
449
450 DPRINTF("Call GETDBREGS for the child process (r1)\n");
451 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
452
453 DPRINTF("State of the debug registers (r1):\n");
454 for (i = 0; i < __arraycount(r1.dr); i++)
455 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
456
457 r1.dr[reg] = (long)(intptr_t)&watchme;
458 DPRINTF("Set DR%d (r1.dr[%d]) to new value %" PRIxREGISTER "\n",
459 reg, reg, r1.dr[reg]);
460
461 r1.dr[7] = dr7.raw;
462 DPRINTF("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n",
463 r1.dr[7]);
464
465 DPRINTF("New state of the debug registers (r1):\n");
466 for (i = 0; i < __arraycount(r1.dr); i++)
467 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
468
469 DPRINTF("Call SETDBREGS for the child process (r1)\n");
470 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
471
472 DPRINTF("Call CONTINUE for the child process\n");
473 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
474
475 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
476 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
477
478 validate_status_stopped(status, SIGTRAP);
479
480 DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
481 SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
482
483 DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
484 DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
485 info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
486 info.psi_siginfo.si_errno);
487
488 DPRINTF("Before checking siginfo_t\n");
489 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
490 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_DBREG);
491
492 DPRINTF("Call CONTINUE for the child process\n");
493 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
494
495 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
496 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
497
498 validate_status_stopped(status, sigval);
499
500 DPRINTF("Before resuming the child process where it left off and "
501 "without signal to be sent\n");
502 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
503
504 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
505 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
506
507 validate_status_exited(status, exitval);
508
509 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
510 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
511 }
512
513 ATF_TC(dbregs_dr0_trap_variable_writeonly_byte);
514 ATF_TC_HEAD(dbregs_dr0_trap_variable_writeonly_byte, tc)
515 {
516 atf_tc_set_md_var(tc, "descr",
517 "Verify that setting trap with DR0 triggers SIGTRAP "
518 "(break on data writes only and 1 byte mode)");
519 }
520
521 ATF_TC_BODY(dbregs_dr0_trap_variable_writeonly_byte, tc)
522 {
523 /* 0b01 -- break on data write only */
524 /* 0b00 -- 1 byte */
525
526 dbregs_trap_variable(0, 1, 0, true);
527 }
528
529 ATF_TC(dbregs_dr1_trap_variable_writeonly_byte);
530 ATF_TC_HEAD(dbregs_dr1_trap_variable_writeonly_byte, tc)
531 {
532 atf_tc_set_md_var(tc, "descr",
533 "Verify that setting trap with DR1 triggers SIGTRAP "
534 "(break on data writes only and 1 byte mode)");
535 }
536
537 ATF_TC_BODY(dbregs_dr1_trap_variable_writeonly_byte, tc)
538 {
539 /* 0b01 -- break on data write only */
540 /* 0b00 -- 1 byte */
541
542 dbregs_trap_variable(1, 1, 0, true);
543 }
544
545 ATF_TC(dbregs_dr2_trap_variable_writeonly_byte);
546 ATF_TC_HEAD(dbregs_dr2_trap_variable_writeonly_byte, tc)
547 {
548 atf_tc_set_md_var(tc, "descr",
549 "Verify that setting trap with DR2 triggers SIGTRAP "
550 "(break on data writes only and 1 byte mode)");
551 }
552
553 ATF_TC_BODY(dbregs_dr2_trap_variable_writeonly_byte, tc)
554 {
555 /* 0b01 -- break on data write only */
556 /* 0b00 -- 1 byte */
557
558 dbregs_trap_variable(2, 1, 0, true);
559 }
560
561 ATF_TC(dbregs_dr3_trap_variable_writeonly_byte);
562 ATF_TC_HEAD(dbregs_dr3_trap_variable_writeonly_byte, tc)
563 {
564 atf_tc_set_md_var(tc, "descr",
565 "Verify that setting trap with DR3 triggers SIGTRAP "
566 "(break on data writes only and 1 byte mode)");
567 }
568
569 ATF_TC_BODY(dbregs_dr3_trap_variable_writeonly_byte, tc)
570 {
571 /* 0b01 -- break on data write only */
572 /* 0b00 -- 1 byte */
573
574 dbregs_trap_variable(3, 1, 0, true);
575 }
576
577 ATF_TC(dbregs_dr0_trap_variable_writeonly_2bytes);
578 ATF_TC_HEAD(dbregs_dr0_trap_variable_writeonly_2bytes, tc)
579 {
580 atf_tc_set_md_var(tc, "descr",
581 "Verify that setting trap with DR0 triggers SIGTRAP "
582 "(break on data writes only and 2 bytes mode)");
583 }
584
585 ATF_TC_BODY(dbregs_dr0_trap_variable_writeonly_2bytes, tc)
586 {
587 /* 0b01 -- break on data write only */
588 /* 0b01 -- 2 bytes */
589
590 dbregs_trap_variable(0, 1, 1, true);
591 }
592
593 ATF_TC(dbregs_dr1_trap_variable_writeonly_2bytes);
594 ATF_TC_HEAD(dbregs_dr1_trap_variable_writeonly_2bytes, tc)
595 {
596 atf_tc_set_md_var(tc, "descr",
597 "Verify that setting trap with DR1 triggers SIGTRAP "
598 "(break on data writes only and 2 bytes mode)");
599 }
600
601 ATF_TC_BODY(dbregs_dr1_trap_variable_writeonly_2bytes, tc)
602 {
603 /* 0b01 -- break on data write only */
604 /* 0b01 -- 2 bytes */
605
606 dbregs_trap_variable(1, 1, 1, true);
607 }
608
609 ATF_TC(dbregs_dr2_trap_variable_writeonly_2bytes);
610 ATF_TC_HEAD(dbregs_dr2_trap_variable_writeonly_2bytes, tc)
611 {
612 atf_tc_set_md_var(tc, "descr",
613 "Verify that setting trap with DR2 triggers SIGTRAP "
614 "(break on data writes only and 2 bytes mode)");
615 }
616
617 ATF_TC_BODY(dbregs_dr2_trap_variable_writeonly_2bytes, tc)
618 {
619 /* 0b01 -- break on data write only */
620 /* 0b01 -- 2 bytes */
621
622 dbregs_trap_variable(2, 1, 1, true);
623 }
624
625 ATF_TC(dbregs_dr3_trap_variable_writeonly_2bytes);
626 ATF_TC_HEAD(dbregs_dr3_trap_variable_writeonly_2bytes, tc)
627 {
628 atf_tc_set_md_var(tc, "descr",
629 "Verify that setting trap with DR3 triggers SIGTRAP "
630 "(break on data writes only and 2 bytes mode)");
631 }
632
633 ATF_TC_BODY(dbregs_dr3_trap_variable_writeonly_2bytes, tc)
634 {
635 /* 0b01 -- break on data write only */
636 /* 0b01 -- 2 bytes */
637
638 dbregs_trap_variable(3, 1, 1, true);
639 }
640
641 ATF_TC(dbregs_dr0_trap_variable_writeonly_4bytes);
642 ATF_TC_HEAD(dbregs_dr0_trap_variable_writeonly_4bytes, tc)
643 {
644 atf_tc_set_md_var(tc, "descr",
645 "Verify that setting trap with DR0 triggers SIGTRAP "
646 "(break on data writes only and 4 bytes mode)");
647 }
648
649 ATF_TC_BODY(dbregs_dr0_trap_variable_writeonly_4bytes, tc)
650 {
651 /* 0b01 -- break on data write only */
652 /* 0b11 -- 4 bytes */
653
654 dbregs_trap_variable(0, 1, 3, true);
655 }
656
657 ATF_TC(dbregs_dr1_trap_variable_writeonly_4bytes);
658 ATF_TC_HEAD(dbregs_dr1_trap_variable_writeonly_4bytes, tc)
659 {
660 atf_tc_set_md_var(tc, "descr",
661 "Verify that setting trap with DR1 triggers SIGTRAP "
662 "(break on data writes only and 4 bytes mode)");
663 }
664
665 ATF_TC_BODY(dbregs_dr1_trap_variable_writeonly_4bytes, tc)
666 {
667 /* 0b01 -- break on data write only */
668 /* 0b11 -- 4 bytes */
669
670 dbregs_trap_variable(1, 1, 3, true);
671 }
672
673 ATF_TC(dbregs_dr2_trap_variable_writeonly_4bytes);
674 ATF_TC_HEAD(dbregs_dr2_trap_variable_writeonly_4bytes, tc)
675 {
676 atf_tc_set_md_var(tc, "descr",
677 "Verify that setting trap with DR2 triggers SIGTRAP "
678 "(break on data writes only and 4 bytes mode)");
679 }
680
681 ATF_TC_BODY(dbregs_dr2_trap_variable_writeonly_4bytes, tc)
682 {
683 /* 0b01 -- break on data write only */
684 /* 0b11 -- 4 bytes */
685
686 dbregs_trap_variable(2, 1, 3, true);
687 }
688
689 ATF_TC(dbregs_dr3_trap_variable_writeonly_4bytes);
690 ATF_TC_HEAD(dbregs_dr3_trap_variable_writeonly_4bytes, tc)
691 {
692 atf_tc_set_md_var(tc, "descr",
693 "Verify that setting trap with DR3 triggers SIGTRAP "
694 "(break on data writes only and 4 bytes mode)");
695 }
696
697 ATF_TC_BODY(dbregs_dr3_trap_variable_writeonly_4bytes, tc)
698 {
699 /* 0b01 -- break on data write only */
700 /* 0b11 -- 4 bytes */
701
702 dbregs_trap_variable(3, 1, 3, true);
703 }
704
705 ATF_TC(dbregs_dr0_trap_variable_readwrite_write_byte);
706 ATF_TC_HEAD(dbregs_dr0_trap_variable_readwrite_write_byte, tc)
707 {
708 atf_tc_set_md_var(tc, "descr",
709 "Verify that setting trap with DR0 triggers SIGTRAP "
710 "(break on data read/write trap in read 1 byte mode)");
711 }
712
713 ATF_TC_BODY(dbregs_dr0_trap_variable_readwrite_write_byte, tc)
714 {
715 /* 0b11 -- break on data write&read */
716 /* 0b00 -- 1 byte */
717
718 dbregs_trap_variable(0, 3, 0, true);
719 }
720
721 ATF_TC(dbregs_dr1_trap_variable_readwrite_write_byte);
722 ATF_TC_HEAD(dbregs_dr1_trap_variable_readwrite_write_byte, tc)
723 {
724 atf_tc_set_md_var(tc, "descr",
725 "Verify that setting trap with DR1 triggers SIGTRAP "
726 "(break on data read/write trap in read 1 byte mode)");
727 }
728
729 ATF_TC_BODY(dbregs_dr1_trap_variable_readwrite_write_byte, tc)
730 {
731 /* 0b11 -- break on data write&read */
732 /* 0b00 -- 1 byte */
733
734 dbregs_trap_variable(1, 3, 0, true);
735 }
736
737 ATF_TC(dbregs_dr2_trap_variable_readwrite_write_byte);
738 ATF_TC_HEAD(dbregs_dr2_trap_variable_readwrite_write_byte, tc)
739 {
740 atf_tc_set_md_var(tc, "descr",
741 "Verify that setting trap with DR2 triggers SIGTRAP "
742 "(break on data read/write trap in read 1 byte mode)");
743 }
744
745 ATF_TC_BODY(dbregs_dr2_trap_variable_readwrite_write_byte, tc)
746 {
747 /* 0b11 -- break on data write&read */
748 /* 0b00 -- 1 byte */
749
750 dbregs_trap_variable(2, 3, 0, true);
751 }
752
753 ATF_TC(dbregs_dr3_trap_variable_readwrite_write_byte);
754 ATF_TC_HEAD(dbregs_dr3_trap_variable_readwrite_write_byte, tc)
755 {
756 atf_tc_set_md_var(tc, "descr",
757 "Verify that setting trap with DR3 triggers SIGTRAP "
758 "(break on data read/write trap in read 1 byte mode)");
759 }
760
761 ATF_TC_BODY(dbregs_dr3_trap_variable_readwrite_write_byte, tc)
762 {
763 /* 0b11 -- break on data write&read */
764 /* 0b00 -- 1 byte */
765
766 dbregs_trap_variable(3, 3, 0, true);
767 }
768
769 ATF_TC(dbregs_dr0_trap_variable_readwrite_write_2bytes);
770 ATF_TC_HEAD(dbregs_dr0_trap_variable_readwrite_write_2bytes, tc)
771 {
772 atf_tc_set_md_var(tc, "descr",
773 "Verify that setting trap with DR0 triggers SIGTRAP "
774 "(break on data read/write trap in read 2 bytes mode)");
775 }
776
777 ATF_TC_BODY(dbregs_dr0_trap_variable_readwrite_write_2bytes, tc)
778 {
779 /* 0b11 -- break on data write&read */
780 /* 0b01 -- 2 bytes */
781
782 dbregs_trap_variable(0, 3, 1, true);
783 }
784
785 ATF_TC(dbregs_dr1_trap_variable_readwrite_write_2bytes);
786 ATF_TC_HEAD(dbregs_dr1_trap_variable_readwrite_write_2bytes, tc)
787 {
788 atf_tc_set_md_var(tc, "descr",
789 "Verify that setting trap with DR1 triggers SIGTRAP "
790 "(break on data read/write trap in read 2 bytes mode)");
791 }
792
793 ATF_TC_BODY(dbregs_dr1_trap_variable_readwrite_write_2bytes, tc)
794 {
795 /* 0b11 -- break on data write&read */
796 /* 0b01 -- 2 bytes */
797
798 dbregs_trap_variable(1, 3, 1, true);
799 }
800
801 ATF_TC(dbregs_dr2_trap_variable_readwrite_write_2bytes);
802 ATF_TC_HEAD(dbregs_dr2_trap_variable_readwrite_write_2bytes, tc)
803 {
804 atf_tc_set_md_var(tc, "descr",
805 "Verify that setting trap with DR2 triggers SIGTRAP "
806 "(break on data read/write trap in read 2 bytes mode)");
807 }
808
809 ATF_TC_BODY(dbregs_dr2_trap_variable_readwrite_write_2bytes, tc)
810 {
811 /* 0b11 -- break on data write&read */
812 /* 0b01 -- 2 bytes */
813
814 dbregs_trap_variable(2, 3, 1, true);
815 }
816
817 ATF_TC(dbregs_dr3_trap_variable_readwrite_write_2bytes);
818 ATF_TC_HEAD(dbregs_dr3_trap_variable_readwrite_write_2bytes, tc)
819 {
820 atf_tc_set_md_var(tc, "descr",
821 "Verify that setting trap with DR3 triggers SIGTRAP "
822 "(break on data read/write trap in read 2 bytes mode)");
823 }
824
825 ATF_TC_BODY(dbregs_dr3_trap_variable_readwrite_write_2bytes, tc)
826 {
827 /* 0b11 -- break on data write&read */
828 /* 0b01 -- 2 bytes */
829
830 dbregs_trap_variable(3, 3, 1, true);
831 }
832
833 ATF_TC(dbregs_dr0_trap_variable_readwrite_write_4bytes);
834 ATF_TC_HEAD(dbregs_dr0_trap_variable_readwrite_write_4bytes, tc)
835 {
836 atf_tc_set_md_var(tc, "descr",
837 "Verify that setting trap with DR0 triggers SIGTRAP "
838 "(break on data read/write trap in read 4 bytes mode)");
839 }
840
841 ATF_TC_BODY(dbregs_dr0_trap_variable_readwrite_write_4bytes, tc)
842 {
843 /* 0b11 -- break on data write&read */
844 /* 0b11 -- 4 bytes */
845
846 dbregs_trap_variable(0, 3, 3, true);
847 }
848
849 ATF_TC(dbregs_dr1_trap_variable_readwrite_write_4bytes);
850 ATF_TC_HEAD(dbregs_dr1_trap_variable_readwrite_write_4bytes, tc)
851 {
852 atf_tc_set_md_var(tc, "descr",
853 "Verify that setting trap with DR1 triggers SIGTRAP "
854 "(break on data read/write trap in read 4 bytes mode)");
855 }
856
857 ATF_TC_BODY(dbregs_dr1_trap_variable_readwrite_write_4bytes, tc)
858 {
859 /* 0b11 -- break on data write&read */
860 /* 0b11 -- 4 bytes */
861
862 dbregs_trap_variable(1, 3, 3, true);
863 }
864
865 ATF_TC(dbregs_dr2_trap_variable_readwrite_write_4bytes);
866 ATF_TC_HEAD(dbregs_dr2_trap_variable_readwrite_write_4bytes, tc)
867 {
868 atf_tc_set_md_var(tc, "descr",
869 "Verify that setting trap with DR2 triggers SIGTRAP "
870 "(break on data read/write trap in read 4 bytes mode)");
871 }
872
873 ATF_TC_BODY(dbregs_dr2_trap_variable_readwrite_write_4bytes, tc)
874 {
875 /* 0b11 -- break on data write&read */
876 /* 0b11 -- 4 bytes */
877
878 dbregs_trap_variable(2, 3, 3, true);
879 }
880
881 ATF_TC(dbregs_dr3_trap_variable_readwrite_write_4bytes);
882 ATF_TC_HEAD(dbregs_dr3_trap_variable_readwrite_write_4bytes, tc)
883 {
884 atf_tc_set_md_var(tc, "descr",
885 "Verify that setting trap with DR3 triggers SIGTRAP "
886 "(break on data read/write trap in read 4 bytes mode)");
887 }
888
889 ATF_TC_BODY(dbregs_dr3_trap_variable_readwrite_write_4bytes, tc)
890 {
891 /* 0b11 -- break on data write&read */
892 /* 0b11 -- 4 bytes */
893
894 dbregs_trap_variable(3, 3, 3, true);
895 }
896
897 ATF_TC(dbregs_dr0_trap_variable_readwrite_read_byte);
898 ATF_TC_HEAD(dbregs_dr0_trap_variable_readwrite_read_byte, tc)
899 {
900 atf_tc_set_md_var(tc, "descr",
901 "Verify that setting trap with DR0 triggers SIGTRAP "
902 "(break on data read/write trap in write 1 byte mode)");
903 }
904
905 ATF_TC_BODY(dbregs_dr0_trap_variable_readwrite_read_byte, tc)
906 {
907 /* 0b11 -- break on data write&read */
908 /* 0b00 -- 1 byte */
909
910 dbregs_trap_variable(0, 3, 0, false);
911 }
912
913 ATF_TC(dbregs_dr1_trap_variable_readwrite_read_byte);
914 ATF_TC_HEAD(dbregs_dr1_trap_variable_readwrite_read_byte, tc)
915 {
916 atf_tc_set_md_var(tc, "descr",
917 "Verify that setting trap with DR1 triggers SIGTRAP "
918 "(break on data read/write trap in write 1 byte mode)");
919 }
920
921 ATF_TC_BODY(dbregs_dr1_trap_variable_readwrite_read_byte, tc)
922 {
923 /* 0b11 -- break on data write&read */
924 /* 0b00 -- 1 byte */
925
926 dbregs_trap_variable(1, 3, 0, false);
927 }
928
929 ATF_TC(dbregs_dr2_trap_variable_readwrite_read_byte);
930 ATF_TC_HEAD(dbregs_dr2_trap_variable_readwrite_read_byte, tc)
931 {
932 atf_tc_set_md_var(tc, "descr",
933 "Verify that setting trap with DR2 triggers SIGTRAP "
934 "(break on data read/write trap in write 1 byte mode)");
935 }
936
937 ATF_TC_BODY(dbregs_dr2_trap_variable_readwrite_read_byte, tc)
938 {
939 /* 0b11 -- break on data write&read */
940 /* 0b00 -- 1 byte */
941
942 dbregs_trap_variable(2, 3, 0, false);
943 }
944
945 ATF_TC(dbregs_dr3_trap_variable_readwrite_read_byte);
946 ATF_TC_HEAD(dbregs_dr3_trap_variable_readwrite_read_byte, tc)
947 {
948 atf_tc_set_md_var(tc, "descr",
949 "Verify that setting trap with DR3 triggers SIGTRAP "
950 "(break on data read/write trap in write 1 byte mode)");
951 }
952
953 ATF_TC_BODY(dbregs_dr3_trap_variable_readwrite_read_byte, tc)
954 {
955 /* 0b11 -- break on data write&read */
956 /* 0b00 -- 1 byte */
957
958 dbregs_trap_variable(3, 3, 0, false);
959 }
960
961 ATF_TC(dbregs_dr0_trap_variable_readwrite_read_2bytes);
962 ATF_TC_HEAD(dbregs_dr0_trap_variable_readwrite_read_2bytes, tc)
963 {
964 atf_tc_set_md_var(tc, "descr",
965 "Verify that setting trap with DR0 triggers SIGTRAP "
966 "(break on data read/write trap in write 2 bytes mode)");
967 }
968
969 ATF_TC_BODY(dbregs_dr0_trap_variable_readwrite_read_2bytes, tc)
970 {
971 /* 0b11 -- break on data write&read */
972 /* 0b01 -- 2 bytes */
973
974 dbregs_trap_variable(0, 3, 1, false);
975 }
976
977 ATF_TC(dbregs_dr1_trap_variable_readwrite_read_2bytes);
978 ATF_TC_HEAD(dbregs_dr1_trap_variable_readwrite_read_2bytes, tc)
979 {
980 atf_tc_set_md_var(tc, "descr",
981 "Verify that setting trap with DR1 triggers SIGTRAP "
982 "(break on data read/write trap in write 2 bytes mode)");
983 }
984
985 ATF_TC_BODY(dbregs_dr1_trap_variable_readwrite_read_2bytes, tc)
986 {
987 /* 0b11 -- break on data write&read */
988 /* 0b01 -- 2 bytes */
989
990 dbregs_trap_variable(1, 3, 1, false);
991 }
992
993 ATF_TC(dbregs_dr2_trap_variable_readwrite_read_2bytes);
994 ATF_TC_HEAD(dbregs_dr2_trap_variable_readwrite_read_2bytes, tc)
995 {
996 atf_tc_set_md_var(tc, "descr",
997 "Verify that setting trap with DR2 triggers SIGTRAP "
998 "(break on data read/write trap in write 2 bytes mode)");
999 }
1000
1001 ATF_TC_BODY(dbregs_dr2_trap_variable_readwrite_read_2bytes, tc)
1002 {
1003 /* 0b11 -- break on data write&read */
1004 /* 0b01 -- 2 bytes */
1005
1006 dbregs_trap_variable(2, 3, 1, false);
1007 }
1008
1009 ATF_TC(dbregs_dr3_trap_variable_readwrite_read_2bytes);
1010 ATF_TC_HEAD(dbregs_dr3_trap_variable_readwrite_read_2bytes, tc)
1011 {
1012 atf_tc_set_md_var(tc, "descr",
1013 "Verify that setting trap with DR3 triggers SIGTRAP "
1014 "(break on data read/write trap in write 2 bytes mode)");
1015 }
1016
1017 ATF_TC_BODY(dbregs_dr3_trap_variable_readwrite_read_2bytes, tc)
1018 {
1019 /* 0b11 -- break on data write&read */
1020 /* 0b01 -- 2 bytes */
1021
1022 dbregs_trap_variable(3, 3, 1, false);
1023 }
1024
1025 ATF_TC(dbregs_dr0_trap_variable_readwrite_read_4bytes);
1026 ATF_TC_HEAD(dbregs_dr0_trap_variable_readwrite_read_4bytes, tc)
1027 {
1028 atf_tc_set_md_var(tc, "descr",
1029 "Verify that setting trap with DR0 triggers SIGTRAP "
1030 "(break on data read/write trap in write 4 bytes mode)");
1031 }
1032
1033 ATF_TC_BODY(dbregs_dr0_trap_variable_readwrite_read_4bytes, tc)
1034 {
1035 /* 0b11 -- break on data write&read */
1036 /* 0b11 -- 4 bytes */
1037
1038 dbregs_trap_variable(0, 3, 3, false);
1039 }
1040
1041 ATF_TC(dbregs_dr1_trap_variable_readwrite_read_4bytes);
1042 ATF_TC_HEAD(dbregs_dr1_trap_variable_readwrite_read_4bytes, tc)
1043 {
1044 atf_tc_set_md_var(tc, "descr",
1045 "Verify that setting trap with DR1 triggers SIGTRAP "
1046 "(break on data read/write trap in write 4 bytes mode)");
1047 }
1048
1049 ATF_TC_BODY(dbregs_dr1_trap_variable_readwrite_read_4bytes, tc)
1050 {
1051 /* 0b11 -- break on data write&read */
1052 /* 0b11 -- 4 bytes */
1053
1054 dbregs_trap_variable(1, 3, 3, false);
1055 }
1056
1057 ATF_TC(dbregs_dr2_trap_variable_readwrite_read_4bytes);
1058 ATF_TC_HEAD(dbregs_dr2_trap_variable_readwrite_read_4bytes, tc)
1059 {
1060 atf_tc_set_md_var(tc, "descr",
1061 "Verify that setting trap with DR2 triggers SIGTRAP "
1062 "(break on data read/write trap in write 4 bytes mode)");
1063 }
1064
1065 ATF_TC_BODY(dbregs_dr2_trap_variable_readwrite_read_4bytes, tc)
1066 {
1067 /* 0b11 -- break on data write&read */
1068 /* 0b11 -- 4 bytes */
1069
1070 dbregs_trap_variable(2, 3, 3, false);
1071 }
1072
1073 ATF_TC(dbregs_dr3_trap_variable_readwrite_read_4bytes);
1074 ATF_TC_HEAD(dbregs_dr3_trap_variable_readwrite_read_4bytes, tc)
1075 {
1076 atf_tc_set_md_var(tc, "descr",
1077 "Verify that setting trap with DR3 triggers SIGTRAP "
1078 "(break on data read/write trap in write 4 bytes mode)");
1079 }
1080
1081 ATF_TC_BODY(dbregs_dr3_trap_variable_readwrite_read_4bytes, tc)
1082 {
1083 /* 0b11 -- break on data write&read */
1084 /* 0b11 -- 4 bytes */
1085
1086 dbregs_trap_variable(3, 3, 3, false);
1087 }
1088
1089 #if defined(HAVE_DBREGS)
1090 ATF_TC(dbregs_dr0_trap_code);
1091 ATF_TC_HEAD(dbregs_dr0_trap_code, tc)
1092 {
1093 atf_tc_set_md_var(tc, "descr",
1094 "Verify that setting trap with DR0 triggers SIGTRAP "
1095 "(break on code execution trap)");
1096 }
1097
1098 ATF_TC_BODY(dbregs_dr0_trap_code, tc)
1099 {
1100 const int exitval = 5;
1101 const int sigval = SIGSTOP;
1102 pid_t child, wpid;
1103 #if defined(TWAIT_HAVE_STATUS)
1104 int status;
1105 #endif
1106 struct dbreg r1;
1107 size_t i;
1108 volatile int watchme = 1;
1109 union u dr7;
1110
1111 struct ptrace_siginfo info;
1112 memset(&info, 0, sizeof(info));
1113
1114 if (!can_we_set_dbregs()) {
1115 atf_tc_skip("Either run this test as root or set sysctl(3) "
1116 "security.models.extensions.user_set_dbregs to 1");
1117 }
1118
1119 dr7.raw = 0;
1120 dr7.bits.global_dr0_breakpoint = 1;
1121 dr7.bits.condition_dr0 = 0; /* 0b00 -- break on code execution */
1122 dr7.bits.len_dr0 = 0; /* 0b00 -- 1 byte */
1123
1124 DPRINTF("Before forking process PID=%d\n", getpid());
1125 SYSCALL_REQUIRE((child = fork()) != -1);
1126 if (child == 0) {
1127 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1128 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1129
1130 DPRINTF("Before raising %s from child\n", strsignal(sigval));
1131 FORKEE_ASSERT(raise(sigval) == 0);
1132
1133 printf("check_happy(%d)=%d\n", watchme, check_happy(watchme));
1134
1135 DPRINTF("Before raising %s from child\n", strsignal(sigval));
1136 FORKEE_ASSERT(raise(sigval) == 0);
1137
1138 DPRINTF("Before exiting of the child process\n");
1139 _exit(exitval);
1140 }
1141 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1142
1143 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1144 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1145
1146 validate_status_stopped(status, sigval);
1147
1148 DPRINTF("Call GETDBREGS for the child process (r1)\n");
1149 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
1150
1151 DPRINTF("State of the debug registers (r1):\n");
1152 for (i = 0; i < __arraycount(r1.dr); i++)
1153 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1154
1155 r1.dr[0] = (long)(intptr_t)check_happy;
1156 DPRINTF("Set DR0 (r1.dr[0]) to new value %" PRIxREGISTER "\n",
1157 r1.dr[0]);
1158
1159 r1.dr[7] = dr7.raw;
1160 DPRINTF("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n",
1161 r1.dr[7]);
1162
1163 DPRINTF("New state of the debug registers (r1):\n");
1164 for (i = 0; i < __arraycount(r1.dr); i++)
1165 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1166
1167 DPRINTF("Call SETDBREGS for the child process (r1)\n");
1168 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
1169
1170 DPRINTF("Call CONTINUE for the child process\n");
1171 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1172
1173 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1174 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1175
1176 validate_status_stopped(status, SIGTRAP);
1177
1178 DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
1179 SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
1180
1181 DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1182 DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
1183 info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1184 info.psi_siginfo.si_errno);
1185
1186 DPRINTF("Before checking siginfo_t\n");
1187 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
1188 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_DBREG);
1189
1190 DPRINTF("Remove code trap from check_happy=%p\n", check_happy);
1191 dr7.bits.global_dr0_breakpoint = 0;
1192 r1.dr[7] = dr7.raw;
1193 DPRINTF("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n",
1194 r1.dr[7]);
1195
1196 DPRINTF("Call SETDBREGS for the child process (r1)\n");
1197 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
1198
1199 DPRINTF("Call CONTINUE for the child process\n");
1200 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1201
1202 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1203 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1204
1205 validate_status_stopped(status, sigval);
1206
1207 DPRINTF("Before resuming the child process where it left off and "
1208 "without signal to be sent\n");
1209 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1210
1211 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1212 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1213
1214 validate_status_exited(status, exitval);
1215
1216 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1217 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1218 }
1219 #endif
1220
1221 #if defined(HAVE_DBREGS)
1222 ATF_TC(dbregs_dr1_trap_code);
1223 ATF_TC_HEAD(dbregs_dr1_trap_code, tc)
1224 {
1225 atf_tc_set_md_var(tc, "descr",
1226 "Verify that setting trap with DR1 triggers SIGTRAP "
1227 "(break on code execution trap)");
1228 }
1229
1230 ATF_TC_BODY(dbregs_dr1_trap_code, tc)
1231 {
1232 const int exitval = 5;
1233 const int sigval = SIGSTOP;
1234 pid_t child, wpid;
1235 #if defined(TWAIT_HAVE_STATUS)
1236 int status;
1237 #endif
1238 struct dbreg r1;
1239 size_t i;
1240 volatile int watchme = 1;
1241 union u dr7;
1242
1243 struct ptrace_siginfo info;
1244 memset(&info, 0, sizeof(info));
1245
1246 if (!can_we_set_dbregs()) {
1247 atf_tc_skip("Either run this test as root or set sysctl(3) "
1248 "security.models.extensions.user_set_dbregs to 1");
1249 }
1250
1251 dr7.raw = 0;
1252 dr7.bits.global_dr1_breakpoint = 1;
1253 dr7.bits.condition_dr1 = 0; /* 0b00 -- break on code execution */
1254 dr7.bits.len_dr1 = 0; /* 0b00 -- 1 byte */
1255
1256 DPRINTF("Before forking process PID=%d\n", getpid());
1257 SYSCALL_REQUIRE((child = fork()) != -1);
1258 if (child == 0) {
1259 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1260 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1261
1262 DPRINTF("Before raising %s from child\n", strsignal(sigval));
1263 FORKEE_ASSERT(raise(sigval) == 0);
1264
1265 printf("check_happy(%d)=%d\n", watchme, check_happy(watchme));
1266
1267 DPRINTF("Before raising %s from child\n", strsignal(sigval));
1268 FORKEE_ASSERT(raise(sigval) == 0);
1269
1270 DPRINTF("Before exiting of the child process\n");
1271 _exit(exitval);
1272 }
1273 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1274
1275 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1276 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1277
1278 validate_status_stopped(status, sigval);
1279
1280 DPRINTF("Call GETDBREGS for the child process (r1)\n");
1281 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
1282
1283 DPRINTF("State of the debug registers (r1):\n");
1284 for (i = 0; i < __arraycount(r1.dr); i++)
1285 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1286
1287 r1.dr[1] = (long)(intptr_t)check_happy;
1288 DPRINTF("Set DR1 (r1.dr[1]) to new value %" PRIxREGISTER "\n",
1289 r1.dr[1]);
1290
1291 r1.dr[7] = dr7.raw;
1292 DPRINTF("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n",
1293 r1.dr[7]);
1294
1295 DPRINTF("New state of the debug registers (r1):\n");
1296 for (i = 0; i < __arraycount(r1.dr); i++)
1297 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1298
1299 DPRINTF("Call SETDBREGS for the child process (r1)\n");
1300 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
1301
1302 DPRINTF("Call CONTINUE for the child process\n");
1303 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1304
1305 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1306 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1307
1308 validate_status_stopped(status, SIGTRAP);
1309
1310 DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
1311 SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
1312
1313 DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1314 DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
1315 info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1316 info.psi_siginfo.si_errno);
1317
1318 DPRINTF("Before checking siginfo_t\n");
1319 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
1320 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_DBREG);
1321
1322 DPRINTF("Remove code trap from check_happy=%p\n", check_happy);
1323 dr7.bits.global_dr1_breakpoint = 0;
1324 r1.dr[7] = dr7.raw;
1325 DPRINTF("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n",
1326 r1.dr[7]);
1327
1328 DPRINTF("Call SETDBREGS for the child process (r1)\n");
1329 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
1330
1331 DPRINTF("Call CONTINUE for the child process\n");
1332 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1333
1334 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1335 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1336
1337 validate_status_stopped(status, sigval);
1338
1339 DPRINTF("Before resuming the child process where it left off and "
1340 "without signal to be sent\n");
1341 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1342
1343 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1344 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1345
1346 validate_status_exited(status, exitval);
1347
1348 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1349 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1350 }
1351 #endif
1352
1353 #if defined(HAVE_DBREGS)
1354 ATF_TC(dbregs_dr2_trap_code);
1355 ATF_TC_HEAD(dbregs_dr2_trap_code, tc)
1356 {
1357 atf_tc_set_md_var(tc, "descr",
1358 "Verify that setting trap with DR2 triggers SIGTRAP "
1359 "(break on code execution trap)");
1360 }
1361
1362 ATF_TC_BODY(dbregs_dr2_trap_code, tc)
1363 {
1364 const int exitval = 5;
1365 const int sigval = SIGSTOP;
1366 pid_t child, wpid;
1367 #if defined(TWAIT_HAVE_STATUS)
1368 int status;
1369 #endif
1370 struct dbreg r1;
1371 size_t i;
1372 volatile int watchme = 1;
1373 union u dr7;
1374
1375 struct ptrace_siginfo info;
1376 memset(&info, 0, sizeof(info));
1377
1378 if (!can_we_set_dbregs()) {
1379 atf_tc_skip("Either run this test as root or set sysctl(3) "
1380 "security.models.extensions.user_set_dbregs to 1");
1381 }
1382
1383 dr7.raw = 0;
1384 dr7.bits.global_dr2_breakpoint = 1;
1385 dr7.bits.condition_dr2 = 0; /* 0b00 -- break on code execution */
1386 dr7.bits.len_dr2 = 0; /* 0b00 -- 1 byte */
1387
1388 DPRINTF("Before forking process PID=%d\n", getpid());
1389 SYSCALL_REQUIRE((child = fork()) != -1);
1390 if (child == 0) {
1391 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1392 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1393
1394 DPRINTF("Before raising %s from child\n", strsignal(sigval));
1395 FORKEE_ASSERT(raise(sigval) == 0);
1396
1397 printf("check_happy(%d)=%d\n", watchme, check_happy(watchme));
1398
1399 DPRINTF("Before raising %s from child\n", strsignal(sigval));
1400 FORKEE_ASSERT(raise(sigval) == 0);
1401
1402 DPRINTF("Before exiting of the child process\n");
1403 _exit(exitval);
1404 }
1405 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1406
1407 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1408 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1409
1410 validate_status_stopped(status, sigval);
1411
1412 DPRINTF("Call GETDBREGS for the child process (r1)\n");
1413 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
1414
1415 DPRINTF("State of the debug registers (r1):\n");
1416 for (i = 0; i < __arraycount(r1.dr); i++)
1417 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1418
1419 r1.dr[2] = (long)(intptr_t)check_happy;
1420 DPRINTF("Set DR2 (r1.dr[2]) to new value %" PRIxREGISTER "\n",
1421 r1.dr[2]);
1422
1423 r1.dr[7] = dr7.raw;
1424 DPRINTF("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n",
1425 r1.dr[7]);
1426
1427 DPRINTF("New state of the debug registers (r1):\n");
1428 for (i = 0; i < __arraycount(r1.dr); i++)
1429 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1430
1431 DPRINTF("Call SETDBREGS for the child process (r1)\n");
1432 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
1433
1434 DPRINTF("Call CONTINUE for the child process\n");
1435 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1436
1437 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1438 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1439
1440 validate_status_stopped(status, SIGTRAP);
1441
1442 DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
1443 SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
1444
1445 DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1446 DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
1447 info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1448 info.psi_siginfo.si_errno);
1449
1450 DPRINTF("Before checking siginfo_t\n");
1451 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
1452 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_DBREG);
1453
1454 DPRINTF("Remove code trap from check_happy=%p\n", check_happy);
1455 dr7.bits.global_dr2_breakpoint = 0;
1456 r1.dr[7] = dr7.raw;
1457 DPRINTF("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n",
1458 r1.dr[7]);
1459
1460 DPRINTF("Call SETDBREGS for the child process (r1)\n");
1461 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
1462
1463 DPRINTF("Call CONTINUE for the child process\n");
1464 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1465
1466 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1467 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1468
1469 validate_status_stopped(status, sigval);
1470
1471 DPRINTF("Before resuming the child process where it left off and "
1472 "without signal to be sent\n");
1473 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1474
1475 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1476 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1477
1478 validate_status_exited(status, exitval);
1479
1480 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1481 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1482 }
1483 #endif
1484
1485 #if defined(HAVE_DBREGS)
1486 ATF_TC(dbregs_dr3_trap_code);
1487 ATF_TC_HEAD(dbregs_dr3_trap_code, tc)
1488 {
1489 atf_tc_set_md_var(tc, "descr",
1490 "Verify that setting trap with DR3 triggers SIGTRAP "
1491 "(break on code execution trap)");
1492 }
1493
1494 ATF_TC_BODY(dbregs_dr3_trap_code, tc)
1495 {
1496 const int exitval = 5;
1497 const int sigval = SIGSTOP;
1498 pid_t child, wpid;
1499 #if defined(TWAIT_HAVE_STATUS)
1500 int status;
1501 #endif
1502 struct dbreg r1;
1503 size_t i;
1504 volatile int watchme = 1;
1505 union u dr7;
1506
1507 struct ptrace_siginfo info;
1508 memset(&info, 0, sizeof(info));
1509
1510 if (!can_we_set_dbregs()) {
1511 atf_tc_skip("Either run this test as root or set sysctl(3) "
1512 "security.models.extensions.user_set_dbregs to 1");
1513 }
1514
1515 dr7.raw = 0;
1516 dr7.bits.global_dr3_breakpoint = 1;
1517 dr7.bits.condition_dr3 = 0; /* 0b00 -- break on code execution */
1518 dr7.bits.len_dr3 = 0; /* 0b00 -- 1 byte */
1519
1520 DPRINTF("Before forking process PID=%d\n", getpid());
1521 SYSCALL_REQUIRE((child = fork()) != -1);
1522 if (child == 0) {
1523 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1524 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1525
1526 DPRINTF("Before raising %s from child\n", strsignal(sigval));
1527 FORKEE_ASSERT(raise(sigval) == 0);
1528
1529 printf("check_happy(%d)=%d\n", watchme, check_happy(watchme));
1530
1531 DPRINTF("Before raising %s from child\n", strsignal(sigval));
1532 FORKEE_ASSERT(raise(sigval) == 0);
1533
1534 DPRINTF("Before exiting of the child process\n");
1535 _exit(exitval);
1536 }
1537 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1538
1539 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1540 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1541
1542 validate_status_stopped(status, sigval);
1543
1544 DPRINTF("Call GETDBREGS for the child process (r1)\n");
1545 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
1546
1547 DPRINTF("State of the debug registers (r1):\n");
1548 for (i = 0; i < __arraycount(r1.dr); i++)
1549 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1550
1551 r1.dr[3] = (long)(intptr_t)check_happy;
1552 DPRINTF("Set DR3 (r1.dr[3]) to new value %" PRIxREGISTER "\n",
1553 r1.dr[3]);
1554
1555 r1.dr[7] = dr7.raw;
1556 DPRINTF("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n",
1557 r1.dr[7]);
1558
1559 DPRINTF("New state of the debug registers (r1):\n");
1560 for (i = 0; i < __arraycount(r1.dr); i++)
1561 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1562
1563 DPRINTF("Call SETDBREGS for the child process (r1)\n");
1564 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
1565
1566 DPRINTF("Call CONTINUE for the child process\n");
1567 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1568
1569 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1570 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1571
1572 validate_status_stopped(status, SIGTRAP);
1573
1574 DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
1575 SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
1576
1577 DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1578 DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
1579 info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1580 info.psi_siginfo.si_errno);
1581
1582 DPRINTF("Before checking siginfo_t\n");
1583 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, SIGTRAP);
1584 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_DBREG);
1585
1586 DPRINTF("Remove code trap from check_happy=%p\n", check_happy);
1587 dr7.bits.global_dr3_breakpoint = 0;
1588 r1.dr[7] = dr7.raw;
1589 DPRINTF("Set DR7 (r1.dr[7]) to new value %" PRIxREGISTER "\n",
1590 r1.dr[7]);
1591
1592 DPRINTF("Call SETDBREGS for the child process (r1)\n");
1593 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
1594
1595 DPRINTF("Call CONTINUE for the child process\n");
1596 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1597
1598 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1599 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1600
1601 validate_status_stopped(status, sigval);
1602
1603 DPRINTF("Before resuming the child process where it left off and "
1604 "without signal to be sent\n");
1605 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1606
1607 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1608 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1609
1610 validate_status_exited(status, exitval);
1611
1612 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1613 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1614 }
1615 #endif
1616
1617 volatile lwpid_t x86_the_lwp_id = 0;
1618
1619 static void __used
1620 x86_lwp_main_func(void *arg)
1621 {
1622 x86_the_lwp_id = _lwp_self();
1623 _lwp_exit();
1624 }
1625
1626 static void
1627 dbregs_dont_inherit_lwp(int reg)
1628 {
1629 const int exitval = 5;
1630 const int sigval = SIGSTOP;
1631 pid_t child, wpid;
1632 #if defined(TWAIT_HAVE_STATUS)
1633 int status;
1634 #endif
1635 ptrace_state_t state;
1636 const int slen = sizeof(state);
1637 ptrace_event_t event;
1638 const int elen = sizeof(event);
1639 ucontext_t uc;
1640 lwpid_t lid;
1641 static const size_t ssize = 16*1024;
1642 void *stack;
1643 size_t i;
1644 struct dbreg r1;
1645 struct dbreg r2;
1646
1647 if (!can_we_set_dbregs()) {
1648 atf_tc_skip("Either run this test as root or set sysctl(3) "
1649 "security.models.extensions.user_set_dbregs to 1");
1650 }
1651
1652 DPRINTF("Before forking process PID=%d\n", getpid());
1653 SYSCALL_REQUIRE((child = fork()) != -1);
1654 if (child == 0) {
1655 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1656 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1657
1658 DPRINTF("Before raising %s from child\n", strsignal(sigval));
1659 FORKEE_ASSERT(raise(sigval) == 0);
1660
1661 DPRINTF("Before allocating memory for stack in child\n");
1662 FORKEE_ASSERT((stack = malloc(ssize)) != NULL);
1663
1664 DPRINTF("Before making context for new lwp in child\n");
1665 _lwp_makecontext(&uc, x86_lwp_main_func, NULL, NULL, stack,
1666 ssize);
1667
1668 DPRINTF("Before creating new in child\n");
1669 FORKEE_ASSERT(_lwp_create(&uc, 0, &lid) == 0);
1670
1671 DPRINTF("Before waiting for lwp %d to exit\n", lid);
1672 FORKEE_ASSERT(_lwp_wait(lid, NULL) == 0);
1673
1674 DPRINTF("Before verifying that reported %d and running lid %d "
1675 "are the same\n", lid, x86_the_lwp_id);
1676 FORKEE_ASSERT_EQ(lid, x86_the_lwp_id);
1677
1678 DPRINTF("Before exiting of the child process\n");
1679 _exit(exitval);
1680 }
1681 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1682
1683 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1684 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1685
1686 validate_status_stopped(status, sigval);
1687
1688 DPRINTF("Set empty EVENT_MASK for the child %d\n", child);
1689 event.pe_set_event = PTRACE_LWP_CREATE;
1690 SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
1691
1692 DPRINTF("Call GETDBREGS for the child process (r1)\n");
1693 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
1694
1695 DPRINTF("State of the debug registers (r1):\n");
1696 for (i = 0; i < __arraycount(r1.dr); i++)
1697 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1698
1699 r1.dr[reg] = (long)(intptr_t)check_happy;
1700 DPRINTF("Set DR%d (r1.dr[%d]) to new value %" PRIxREGISTER "\n",
1701 reg, reg, r1.dr[0]);
1702
1703 DPRINTF("New state of the debug registers (r1):\n");
1704 for (i = 0; i < __arraycount(r1.dr); i++)
1705 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1706
1707 DPRINTF("Call SETDBREGS for the child process (r1)\n");
1708 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
1709
1710 DPRINTF("Before resuming the child process where it left off and "
1711 "without signal to be sent\n");
1712 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1713
1714 DPRINTF("Before calling %s() for the child - expected stopped "
1715 "SIGTRAP\n", TWAIT_FNAME);
1716 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1717
1718 validate_status_stopped(status, SIGTRAP);
1719
1720 SYSCALL_REQUIRE(ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
1721
1722 ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_LWP_CREATE);
1723
1724 lid = state.pe_lwp;
1725 DPRINTF("Reported PTRACE_LWP_CREATE event with lid %d\n", lid);
1726
1727 DPRINTF("Call GETDBREGS for the child process new lwp (r2)\n");
1728 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &r2, lid) != -1);
1729
1730 DPRINTF("State of the debug registers (r2):\n");
1731 for (i = 0; i < __arraycount(r2.dr); i++)
1732 DPRINTF("r2[%zu]=%" PRIxREGISTER "\n", i, r2.dr[i]);
1733
1734 DPRINTF("Assert that (r1) and (r2) are not the same\n");
1735 ATF_REQUIRE(memcmp(&r1, &r2, sizeof(r1)) != 0);
1736
1737 DPRINTF("Before resuming the child process where it left off and "
1738 "without signal to be sent\n");
1739 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1740
1741 DPRINTF("Before calling %s() for the child - expected exited\n",
1742 TWAIT_FNAME);
1743 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1744
1745 validate_status_exited(status, exitval);
1746
1747 DPRINTF("Before calling %s() for the child - expected no process\n",
1748 TWAIT_FNAME);
1749 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1750 }
1751
1752 ATF_TC(dbregs_dr0_dont_inherit_lwp);
1753 ATF_TC_HEAD(dbregs_dr0_dont_inherit_lwp, tc)
1754 {
1755 atf_tc_set_md_var(tc, "descr",
1756 "Verify that 1 LWP creation is intercepted by ptrace(2) with "
1757 "EVENT_MASK set to PTRACE_LWP_CREATE and Debug Register 0 from "
1758 "the forker thread is not inherited");
1759 }
1760
1761 ATF_TC_BODY(dbregs_dr0_dont_inherit_lwp, tc)
1762 {
1763 dbregs_dont_inherit_lwp(0);
1764 }
1765
1766 ATF_TC(dbregs_dr1_dont_inherit_lwp);
1767 ATF_TC_HEAD(dbregs_dr1_dont_inherit_lwp, tc)
1768 {
1769 atf_tc_set_md_var(tc, "descr",
1770 "Verify that 1 LWP creation is intercepted by ptrace(2) with "
1771 "EVENT_MASK set to PTRACE_LWP_CREATE and Debug Register 1 from "
1772 "the forker thread is not inherited");
1773 }
1774
1775 ATF_TC_BODY(dbregs_dr1_dont_inherit_lwp, tc)
1776 {
1777 dbregs_dont_inherit_lwp(1);
1778 }
1779
1780 ATF_TC(dbregs_dr2_dont_inherit_lwp);
1781 ATF_TC_HEAD(dbregs_dr2_dont_inherit_lwp, tc)
1782 {
1783 atf_tc_set_md_var(tc, "descr",
1784 "Verify that 1 LWP creation is intercepted by ptrace(2) with "
1785 "EVENT_MASK set to PTRACE_LWP_CREATE and Debug Register 2 from "
1786 "the forker thread is not inherited");
1787 }
1788
1789 ATF_TC_BODY(dbregs_dr2_dont_inherit_lwp, tc)
1790 {
1791 dbregs_dont_inherit_lwp(2);
1792 }
1793
1794 ATF_TC(dbregs_dr3_dont_inherit_lwp);
1795 ATF_TC_HEAD(dbregs_dr3_dont_inherit_lwp, tc)
1796 {
1797 atf_tc_set_md_var(tc, "descr",
1798 "Verify that 1 LWP creation is intercepted by ptrace(2) with "
1799 "EVENT_MASK set to PTRACE_LWP_CREATE and Debug Register 3 from "
1800 "the forker thread is not inherited");
1801 }
1802
1803 ATF_TC_BODY(dbregs_dr3_dont_inherit_lwp, tc)
1804 {
1805 dbregs_dont_inherit_lwp(3);
1806 }
1807
1808 static void
1809 dbregs_dont_inherit_execve(int reg)
1810 {
1811 const int sigval = SIGTRAP;
1812 pid_t child, wpid;
1813 #if defined(TWAIT_HAVE_STATUS)
1814 int status;
1815 #endif
1816 size_t i;
1817 struct dbreg r1;
1818 struct dbreg r2;
1819
1820 struct ptrace_siginfo info;
1821 memset(&info, 0, sizeof(info));
1822
1823 if (!can_we_set_dbregs()) {
1824 atf_tc_skip("Either run this test as root or set sysctl(3) "
1825 "security.models.extensions.user_set_dbregs to 1");
1826 }
1827
1828 DPRINTF("Before forking process PID=%d\n", getpid());
1829 SYSCALL_REQUIRE((child = fork()) != -1);
1830 if (child == 0) {
1831 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
1832 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
1833
1834 DPRINTF("Before raising %s from child\n", strsignal(sigval));
1835 FORKEE_ASSERT(raise(sigval) == 0);
1836
1837 DPRINTF("Before calling execve(2) from child\n");
1838 execlp("/bin/echo", "/bin/echo", NULL);
1839
1840 FORKEE_ASSERT(0 && "Not reached");
1841 }
1842 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
1843
1844 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1845 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1846
1847 validate_status_stopped(status, sigval);
1848
1849 DPRINTF("Call GETDBREGS for the child process (r1)\n");
1850 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &r1, 0) != -1);
1851
1852 DPRINTF("State of the debug registers (r1):\n");
1853 for (i = 0; i < __arraycount(r1.dr); i++)
1854 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1855
1856 r1.dr[reg] = (long)(intptr_t)check_happy;
1857 DPRINTF("Set DR%d (r1.dr[%d]) to new value %" PRIxREGISTER "\n",
1858 reg, reg, r1.dr[reg]);
1859
1860 DPRINTF("New state of the debug registers (r1):\n");
1861 for (i = 0; i < __arraycount(r1.dr); i++)
1862 DPRINTF("r1[%zu]=%" PRIxREGISTER "\n", i, r1.dr[i]);
1863
1864 DPRINTF("Call SETDBREGS for the child process (r1)\n");
1865 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &r1, 0) != -1);
1866
1867 DPRINTF("Before resuming the child process where it left off and "
1868 "without signal to be sent\n");
1869 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1870
1871 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1872 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1873
1874 validate_status_stopped(status, sigval);
1875
1876 DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
1877 SYSCALL_REQUIRE(ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
1878
1879 DPRINTF("Signal traced to lwpid=%d\n", info.psi_lwpid);
1880 DPRINTF("Signal properties: si_signo=%#x si_code=%#x si_errno=%#x\n",
1881 info.psi_siginfo.si_signo, info.psi_siginfo.si_code,
1882 info.psi_siginfo.si_errno);
1883
1884 ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
1885 ATF_REQUIRE_EQ(info.psi_siginfo.si_code, TRAP_EXEC);
1886
1887 DPRINTF("Call GETDBREGS for the child process after execve(2)\n");
1888 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &r2, 0) != -1);
1889
1890 DPRINTF("State of the debug registers (r2):\n");
1891 for (i = 0; i < __arraycount(r2.dr); i++)
1892 DPRINTF("r2[%zu]=%" PRIxREGISTER "\n", i, r2.dr[i]);
1893
1894 DPRINTF("Assert that (r1) and (r2) are not the same\n");
1895 ATF_REQUIRE(memcmp(&r1, &r2, sizeof(r1)) != 0);
1896
1897 DPRINTF("Before resuming the child process where it left off and "
1898 "without signal to be sent\n");
1899 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
1900
1901 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1902 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
1903
1904 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
1905 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
1906 }
1907
1908 ATF_TC(dbregs_dr0_dont_inherit_execve);
1909 ATF_TC_HEAD(dbregs_dr0_dont_inherit_execve, tc)
1910 {
1911 atf_tc_set_md_var(tc, "descr",
1912 "Verify that execve(2) is intercepted by tracer and Debug "
1913 "Register 0 is reset");
1914 }
1915
1916 ATF_TC_BODY(dbregs_dr0_dont_inherit_execve, tc)
1917 {
1918 dbregs_dont_inherit_execve(0);
1919 }
1920
1921 ATF_TC(dbregs_dr1_dont_inherit_execve);
1922 ATF_TC_HEAD(dbregs_dr1_dont_inherit_execve, tc)
1923 {
1924 atf_tc_set_md_var(tc, "descr",
1925 "Verify that execve(2) is intercepted by tracer and Debug "
1926 "Register 1 is reset");
1927 }
1928
1929 ATF_TC_BODY(dbregs_dr1_dont_inherit_execve, tc)
1930 {
1931 dbregs_dont_inherit_execve(1);
1932 }
1933
1934 ATF_TC(dbregs_dr2_dont_inherit_execve);
1935 ATF_TC_HEAD(dbregs_dr2_dont_inherit_execve, tc)
1936 {
1937 atf_tc_set_md_var(tc, "descr",
1938 "Verify that execve(2) is intercepted by tracer and Debug "
1939 "Register 2 is reset");
1940 }
1941
1942 ATF_TC_BODY(dbregs_dr2_dont_inherit_execve, tc)
1943 {
1944 dbregs_dont_inherit_execve(2);
1945 }
1946
1947 ATF_TC(dbregs_dr3_dont_inherit_execve);
1948 ATF_TC_HEAD(dbregs_dr3_dont_inherit_execve, tc)
1949 {
1950 atf_tc_set_md_var(tc, "descr",
1951 "Verify that execve(2) is intercepted by tracer and Debug "
1952 "Register 3 is reset");
1953 }
1954
1955 ATF_TC_BODY(dbregs_dr3_dont_inherit_execve, tc)
1956 {
1957 dbregs_dont_inherit_execve(3);
1958 }
1959
1960 /// ----------------------------------------------------------------------------
1961
1962 ATF_TC(x86_cve_2018_8897);
1963 ATF_TC_HEAD(x86_cve_2018_8897, tc)
1964 {
1965 atf_tc_set_md_var(tc, "descr",
1966 "Verify mitigation for CVE-2018-8897 (POP SS debug exception)");
1967 }
1968
1969 #define X86_CVE_2018_8897_PAGE 0x5000 /* page addressable by 32-bit registers */
1970
1971 static void
1972 x86_cve_2018_8897_trigger(void)
1973 {
1974 /*
1975 * A function to trigger the POP SS (CVE-2018-8897) vulnerability
1976 *
1977 * ifdef __x86_64__
1978 *
1979 * We need to switch to 32-bit mode execution on 64-bit kernel.
1980 * This is achieved with far jump instruction and GDT descriptor
1981 * set to 32-bit CS selector. The 32-bit CS selector is kernel
1982 * specific, in the NetBSD case registered as GUCODE32_SEL
1983 * that is equal to (14 (decimal) << 3) with GDT and user
1984 * privilege level (this makes it 0x73).
1985 *
1986 * In UNIX as(1) assembly x86_64 far jump is coded as ljmp.
1987 * amd64 ljmp requires an indirect address with cs:RIP.
1988 *
1989 * When we are running in 32-bit mode, it's similar to the
1990 * mode as if the binary had been launched in netbsd32.
1991 *
1992 * There are two versions of this exploit, one with RIP
1993 * relative code and the other with static addresses.
1994 * The first one is PIE code aware, the other no-PIE one.
1995 *
1996 *
1997 * After switching to the 32-bit mode we can move on to the remaining
1998 * part of the exploit.
1999 *
2000 * endif // __x86_64__
2001 *
2002 * Set the stack pointer to the page we allocated earlier. Remember
2003 * that we put an SS selector exactly at this address, so we can pop.
2004 *
2005 * movl $0x5000,%esp
2006 *
2007 * Pop the SS selector off the stack. This reloads the SS selector,
2008 * which is fine. Remember that we set DR0 at address 0x5000, which
2009 * we are now reading. Therefore, on this instruction, the CPU will
2010 * raise a #DB exception.
2011 *
2012 * But the "pop %ss" instruction is special: it blocks exceptions
2013 * until the next instruction is executed. So the #DB that we just
2014 * raised is actually blocked.
2015 *
2016 * pop %ss
2017 *
2018 * We are still here, and didn't receive the #DB. After we execute
2019 * this instruction, the effect of "pop %ss" will disappear, and
2020 * we will receive the #DB for real.
2021 *
2022 * int $4
2023 *
2024 * Here the bug happens. We executed "int $4", so we entered the
2025 * kernel, with interrupts disabled. The #DB that was pending is
2026 * received. But, it is received immediately in kernel mode, and is
2027 * _NOT_ received when interrupts are enabled again.
2028 *
2029 * It means that, in the first instruction of the $4 handler, we
2030 * think we are safe with interrupts disabled. But we aren't, and
2031 * just got interrupted.
2032 *
2033 * The new interrupt handler doesn't handle this particular context:
2034 * we are entered in kernel mode, the previous context was kernel
2035 * mode too but it still had the user context loaded.
2036 *
2037 * We find ourselves not doing a 'swapgs'. At the end of the day, it
2038 * means that we call trap() with a curcpu() that is fully
2039 * controllable by userland. From then on, it is easy to escalate
2040 * privileges.
2041 *
2042 * With SVS it also means we don't switch CR3, so this results in a
2043 * triple fault, which this time cannot be turned to a privilege
2044 * escalation.
2045 */
2046
2047 #if __x86_64__
2048 #if __PIE__
2049 void *csRIP;
2050
2051 csRIP = malloc(sizeof(int) + sizeof(short));
2052 FORKEE_ASSERT(csRIP != NULL);
2053
2054 __asm__ __volatile__(
2055 " leal 24(%%eip), %%eax\n\t"
2056 " movq %0, %%rdx\n\t"
2057 " movl %%eax, (%%rdx)\n\t"
2058 " movw $0x73, 4(%%rdx)\n\t"
2059 " movq %1, %%rax\n\t"
2060 " ljmp *(%%rax)\n\t"
2061 " .code32\n\t"
2062 " movl $0x5000, %%esp\n\t"
2063 " pop %%ss\n\t"
2064 " int $4\n\t"
2065 " .code64\n\t"
2066 : "=m"(csRIP)
2067 : "m"(csRIP)
2068 : "%rax", "%rdx", "%rsp"
2069 );
2070 #else /* !__PIE__ */
2071 __asm__ __volatile__(
2072 " movq $farjmp32, %%rax\n\t"
2073 " ljmp *(%%rax)\n\t"
2074 "farjmp32:\n\t"
2075 " .long trigger32\n\t"
2076 " .word 0x73\n\t"
2077 " .code32\n\t"
2078 "trigger32:\n\t"
2079 " movl $0x5000, %%esp\n\t"
2080 " pop %%ss\n\t"
2081 " int $4\n\t"
2082 " .code64\n\t"
2083 :
2084 :
2085 : "%rax", "%rsp"
2086 );
2087 #endif
2088 #elif __i386__
2089 __asm__ __volatile__(
2090 "movl $0x5000, %%esp\n\t"
2091 "pop %%ss\n\t"
2092 "int $4\n\t"
2093 :
2094 :
2095 : "%esp"
2096 );
2097 #endif
2098 }
2099
2100 ATF_TC_BODY(x86_cve_2018_8897, tc)
2101 {
2102 const int sigval = SIGSTOP;
2103 pid_t child, wpid;
2104 #if defined(TWAIT_HAVE_STATUS)
2105 int status;
2106 #endif
2107 char *trap_page;
2108 struct dbreg db;
2109
2110
2111 if (!can_we_set_dbregs()) {
2112 atf_tc_skip("Either run this test as root or set sysctl(3) "
2113 "security.models.extensions.user_set_dbregs to 1");
2114 }
2115
2116 DPRINTF("Before forking process PID=%d\n", getpid());
2117 SYSCALL_REQUIRE((child = fork()) != -1);
2118 if (child == 0) {
2119 DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
2120 FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
2121
2122 trap_page = mmap((void *)X86_CVE_2018_8897_PAGE,
2123 sysconf(_SC_PAGESIZE), PROT_READ|PROT_WRITE,
2124 MAP_FIXED|MAP_ANON|MAP_PRIVATE, -1, 0);
2125
2126 /* trigger page fault */
2127 memset(trap_page, 0, sysconf(_SC_PAGESIZE));
2128
2129 // kernel GDT
2130 #if __x86_64__
2131 /* SS selector (descriptor 9 (0x4f >> 3)) */
2132 *trap_page = 0x4f;
2133 #elif __i386__
2134 /* SS selector (descriptor 4 (0x23 >> 3)) */
2135 *trap_page = 0x23;
2136 #endif
2137
2138 DPRINTF("Before raising %s from child\n", strsignal(sigval));
2139 FORKEE_ASSERT(raise(sigval) == 0);
2140
2141 x86_cve_2018_8897_trigger();
2142
2143 /* NOTREACHED */
2144 FORKEE_ASSERTX(0 && "This shall not be reached");
2145 }
2146 DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
2147
2148 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2149 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2150
2151 validate_status_stopped(status, sigval);
2152
2153 DPRINTF("Call GETDBREGS for the child process\n");
2154 SYSCALL_REQUIRE(ptrace(PT_GETDBREGS, child, &db, 0) != -1);
2155
2156 /*
2157 * Set up the dbregs. We put the 0x5000 address in DR0.
2158 * It means that, the first time we touch this, the CPU will trigger a
2159 * #DB exception.
2160 */
2161 db.dr[0] = X86_CVE_2018_8897_PAGE;
2162 db.dr[7] = 0x30003;
2163
2164 DPRINTF("Call SETDBREGS for the child process\n");
2165 SYSCALL_REQUIRE(ptrace(PT_SETDBREGS, child, &db, 0) != -1);
2166
2167 DPRINTF("Before resuming the child process where it left off and "
2168 "without signal to be sent\n");
2169 SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
2170
2171 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2172 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2173
2174 // In this test we receive SIGFPE, is this appropriate?
2175 // validate_status_stopped(status, SIGFPE);
2176
2177 DPRINTF("Kill the child process\n");
2178 SYSCALL_REQUIRE(ptrace(PT_KILL, child, NULL, 0) != -1);
2179
2180 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2181 TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
2182
2183 validate_status_signaled(status, SIGKILL, 0);
2184
2185 DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
2186 TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
2187 }
2188
2189 /// ----------------------------------------------------------------------------
2190
2191 #define ATF_TP_ADD_TCS_PTRACE_WAIT_X86() \
2192 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_print); \
2193 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr0); \
2194 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr1); \
2195 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr2); \
2196 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr3); \
2197 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr0_yield); \
2198 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr1_yield); \
2199 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr2_yield); \
2200 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr3_yield); \
2201 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr0_continued); \
2202 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr1_continued); \
2203 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr2_continued); \
2204 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_preserve_dr3_continued); \
2205 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_writeonly_byte); \
2206 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_writeonly_byte); \
2207 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_writeonly_byte); \
2208 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_writeonly_byte); \
2209 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_writeonly_2bytes); \
2210 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_writeonly_2bytes); \
2211 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_writeonly_2bytes); \
2212 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_writeonly_2bytes); \
2213 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_writeonly_4bytes); \
2214 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_writeonly_4bytes); \
2215 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_writeonly_4bytes); \
2216 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_writeonly_4bytes); \
2217 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_readwrite_write_byte); \
2218 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_readwrite_write_byte); \
2219 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_readwrite_write_byte); \
2220 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_readwrite_write_byte); \
2221 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_readwrite_write_2bytes); \
2222 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_readwrite_write_2bytes); \
2223 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_readwrite_write_2bytes); \
2224 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_readwrite_write_2bytes); \
2225 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_readwrite_write_4bytes); \
2226 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_readwrite_write_4bytes); \
2227 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_readwrite_write_4bytes); \
2228 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_readwrite_write_4bytes); \
2229 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_readwrite_read_byte); \
2230 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_readwrite_read_byte); \
2231 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_readwrite_read_byte); \
2232 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_readwrite_read_byte); \
2233 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_readwrite_read_2bytes); \
2234 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_readwrite_read_2bytes); \
2235 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_readwrite_read_2bytes); \
2236 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_readwrite_read_2bytes); \
2237 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_variable_readwrite_read_4bytes); \
2238 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_variable_readwrite_read_4bytes); \
2239 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_variable_readwrite_read_4bytes); \
2240 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_variable_readwrite_read_4bytes); \
2241 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_trap_code); \
2242 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_trap_code); \
2243 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_trap_code); \
2244 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_trap_code); \
2245 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_dont_inherit_lwp); \
2246 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_dont_inherit_lwp); \
2247 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_dont_inherit_lwp); \
2248 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_dont_inherit_lwp); \
2249 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr0_dont_inherit_execve); \
2250 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr1_dont_inherit_execve); \
2251 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr2_dont_inherit_execve); \
2252 ATF_TP_ADD_TC_HAVE_DBREGS(tp, dbregs_dr3_dont_inherit_execve); \
2253 ATF_TP_ADD_TC_HAVE_DBREGS(tp, x86_cve_2018_8897);
2254 #else
2255 #define ATF_TP_ADD_TCS_PTRACE_WAIT_X86()
2256 #endif
2257