xref: /netbsd-src/tests/lib/libc/sys/t_ptrace_x86_wait.h (revision 4ee7ae60519fb10951291c2783fc107b0d9e7e01)
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