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