t_ptrace_wait.h revision 1.38 1 /* $NetBSD: t_ptrace_wait.h,v 1.38 2025/05/02 02:24:44 riastradh Exp $ */
2
3 /*-
4 * Copyright (c) 2016, 2017, 2018, 2019 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 /* Detect plain wait(2) use-case */
30 #if !defined(TWAIT_WAITPID) && \
31 !defined(TWAIT_WAITID) && \
32 !defined(TWAIT_WAIT3) && \
33 !defined(TWAIT_WAIT4) && \
34 !defined(TWAIT_WAIT6)
35 #define TWAIT_WAIT
36 #endif
37
38 /*
39 * There are two classes of wait(2)-like functions:
40 * - wait4(2)-like accepting pid_t, optional options parameter, struct rusage*
41 * - wait6(2)-like accepting idtype_t, id_t, struct wrusage, mandatory options
42 *
43 * The TWAIT_FNAME value is to be used for convenience in debug messages.
44 *
45 * The TWAIT_GENERIC() macro is designed to reuse the same unmodified
46 * code with as many wait(2)-like functions as possible.
47 *
48 * In a common use-case wait4(2) and wait6(2)-like function can work the almost
49 * the same way, however there are few important differences:
50 * wait6(2) must specify P_PID for idtype to match wpid from wait4(2).
51 * To behave like wait4(2), wait6(2) the 'options' to wait must include
52 * WEXITED|WTRUNCATED.
53 *
54 * There are two helper macros (they purpose it to mach more than one
55 * wait(2)-like function):
56 * The TWAIT_HAVE_STATUS - specifies whether a function can retrieve
57 * status (as integer value).
58 * The TWAIT_HAVE_PID - specifies whether a function can request
59 * exact process identifier
60 * The TWAIT_HAVE_RUSAGE - specifies whether a function can request
61 * the struct rusage value
62 *
63 */
64
65 #if defined(TWAIT_WAIT)
66 # define TWAIT_FNAME "wait"
67 # define TWAIT_WAIT4TYPE(a,b,c,d) wait((b))
68 # define TWAIT_GENERIC(a,b,c) wait((b))
69 # define TWAIT_HAVE_STATUS 1
70 #elif defined(TWAIT_WAITPID)
71 # define TWAIT_FNAME "waitpid"
72 # define TWAIT_WAIT4TYPE(a,b,c,d) waitpid((a),(b),(c))
73 # define TWAIT_GENERIC(a,b,c) waitpid((a),(b),(c))
74 # define TWAIT_HAVE_PID 1
75 # define TWAIT_HAVE_STATUS 1
76 # define TWAIT_HAVE_OPTIONS 1
77 #elif defined(TWAIT_WAITID)
78 # define TWAIT_FNAME "waitid"
79 # define TWAIT_GENERIC(a,b,c) \
80 waitid(P_PID,(a),NULL,(c)|WEXITED|WTRAPPED)
81 # define TWAIT_WAIT6TYPE(a,b,c,d,e,f) waitid((a),(b),(f),(d))
82 # define TWAIT_HAVE_PID 1
83 # define TWAIT_HAVE_OPTIONS 1
84 #elif defined(TWAIT_WAIT3)
85 # define TWAIT_FNAME "wait3"
86 # define TWAIT_WAIT4TYPE(a,b,c,d) wait3((b),(c),(d))
87 # define TWAIT_GENERIC(a,b,c) wait3((b),(c),NULL)
88 # define TWAIT_HAVE_STATUS 1
89 # define TWAIT_HAVE_RUSAGE 1
90 # define TWAIT_HAVE_OPTIONS 1
91 #elif defined(TWAIT_WAIT4)
92 # define TWAIT_FNAME "wait4"
93 # define TWAIT_WAIT4TYPE(a,b,c,d) wait4((a),(b),(c),(d))
94 # define TWAIT_GENERIC(a,b,c) wait4((a),(b),(c),NULL)
95 # define TWAIT_HAVE_PID 1
96 # define TWAIT_HAVE_STATUS 1
97 # define TWAIT_HAVE_RUSAGE 1
98 # define TWAIT_HAVE_OPTIONS 1
99 #elif defined(TWAIT_WAIT6)
100 # define TWAIT_FNAME "wait6"
101 # define TWAIT_WAIT6TYPE(a,b,c,d,e,f) wait6((a),(b),(c),(d),(e),(f))
102 # define TWAIT_GENERIC(a,b,c) \
103 wait6(P_PID,(a),(b),(c)|WEXITED|WTRAPPED,NULL,NULL)
104 # define TWAIT_HAVE_PID 1
105 # define TWAIT_HAVE_STATUS 1
106 # define TWAIT_HAVE_OPTIONS 1
107 #endif
108
109 /*
110 * There are 3 groups of tests:
111 * - TWAIT_GENERIC() (wait, wait2, waitpid, wait3, wait4, wait6)
112 * - TWAIT_WAIT4TYPE() (wait2, waitpid, wait3, wait4)
113 * - TWAIT_WAIT6TYPE() (waitid, wait6)
114 *
115 * Tests only in the above categories are allowed. However some tests are not
116 * possible in the context requested functionality to be verified, therefore
117 * there are helper macros:
118 * - TWAIT_HAVE_PID (wait2, waitpid, waitid, wait4, wait6)
119 * - TWAIT_HAVE_STATUS (wait, wait2, waitpid, wait3, wait4, wait6)
120 * - TWAIT_HAVE_RUSAGE (wait3, wait4)
121 * - TWAIT_HAVE_RETPID (wait, wait2, waitpid, wait3, wait4, wait6)
122 *
123 * If there is an intention to test e.g. wait6(2) specific features in the
124 * ptrace(2) context, find the most matching group and with #ifdefs reduce
125 * functionality of less featured than wait6(2) interface (TWAIT_WAIT6TYPE).
126 *
127 * For clarity never use negative preprocessor checks, like:
128 * #if !defined(TWAIT_WAIT4)
129 * always refer to checks for positive values.
130 */
131
132 #define TEST_REQUIRE_EQ(x, y) \
133 do { \
134 uintmax_t vx = (x); \
135 uintmax_t vy = (y); \
136 int ret = vx == vy; \
137 if (!ret) \
138 ATF_REQUIRE_EQ_MSG(vx, vy, "%s(%ju) == %s(%ju)", \
139 #x, vx, #y, vy); \
140 } while (/*CONSTCOND*/0)
141
142 /*
143 * A child process cannot call atf functions and expect them to magically
144 * work like in the parent.
145 * The printf(3) messaging from a child will not work out of the box as well
146 * without establishing a communication protocol with its parent. To not
147 * overcomplicate the tests - do not log from a child and use err(3)/errx(3)
148 * wrapped with FORKEE_ASSERT()/FORKEE_ASSERTX() as that is guaranteed to work.
149 */
150 #define FORKEE_ASSERT_EQ(x, y) \
151 do { \
152 uintmax_t vx = (x); \
153 uintmax_t vy = (y); \
154 int ret = vx == vy; \
155 if (!ret) \
156 errx(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: " \
157 "%s(%ju) == %s(%ju)", __FILE__, __LINE__, __func__, \
158 #x, vx, #y, vy); \
159 } while (/*CONSTCOND*/0)
160
161 #define FORKEE_ASSERT_NEQ(x, y) \
162 do { \
163 uintmax_t vx = (x); \
164 uintmax_t vy = (y); \
165 int ret = vx != vy; \
166 if (!ret) \
167 errx(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: " \
168 "%s(%ju) != %s(%ju)", __FILE__, __LINE__, __func__, \
169 #x, vx, #y, vy); \
170 } while (/*CONSTCOND*/0)
171
172 __unused /* used by FORKEE_ASSERT_MEMEQ, otherwise not used */
173 static void
174 hexdump(const char *title, const void *buf, size_t len)
175 {
176 const unsigned char *p = buf;
177 size_t i;
178
179 fprintf(stderr, "%s (%zu bytes)\n", title, len);
180 for (i = 0; i < len; i++) {
181 if ((i % 8) == 0)
182 fprintf(stderr, " ");
183 fprintf(stderr, "%02hhx", p[i]);
184 if ((i % 16) == 0)
185 fprintf(stderr, "\n");
186 }
187 if (i % 16)
188 fprintf(stderr, "\n");
189 }
190
191 #define FORKEE_ASSERT_MEMEQ(x, y, n) \
192 do { \
193 const void *const vx = (x); \
194 const void *const vy = (y); \
195 const size_t vn = (n); \
196 \
197 if (__predict_true(memcmp(vx, vy, vn) == 0)) \
198 break; \
199 fprintf(stderr, "%s != %s (%s = %zu bytes)\n", #x, #y, #n, vn); \
200 hexdump(#x, vx, vn); \
201 hexdump(#y, vy, vn); \
202 } while (/*CONSTCOND*/0)
203
204 #define FORKEE_ASSERTX(x) \
205 do { \
206 int ret = (x); \
207 if (!ret) \
208 errx(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: %s",\
209 __FILE__, __LINE__, __func__, #x); \
210 } while (/*CONSTCOND*/0)
211
212 #define FORKEE_ASSERT(x) \
213 do { \
214 int ret = (x); \
215 if (!ret) \
216 err(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: %s",\
217 __FILE__, __LINE__, __func__, #x); \
218 } while (/*CONSTCOND*/0)
219
220 #define FORKEE_PTHREAD(x) \
221 do { \
222 int _forkee_pthread_error = (x); \
223 if (_forkee_pthread_error) { \
224 errno = _forkee_pthread_error; \
225 err(EXIT_FAILURE, "%s:%d %s(): %s", __FILE__, __LINE__, \
226 __func__, #x); \
227 } \
228 } while (/*CONSTCOND*/0)
229
230 /*
231 * Simplify logic for functions using general purpose registers add HAVE_GPREGS
232 *
233 * For platforms that do not implement all needed calls for simplicity assume
234 * that they are unsupported at all.
235 */
236 #if defined(PT_GETREGS) \
237 && defined(PT_SETREGS) \
238 && defined(PTRACE_REG_PC) \
239 && defined(PTRACE_REG_SET_PC) \
240 && defined(PTRACE_REG_SP) \
241 && defined(PTRACE_REG_INTRV)
242 #define HAVE_GPREGS
243 #endif
244
245 /* Add guards for floating point registers */
246 #if defined(PT_GETFPREGS) \
247 && defined(PT_SETFPREGS)
248 #define HAVE_FPREGS
249 #endif
250
251 /* Add guards for cpu debug registers */
252 #if defined(PT_GETDBREGS) \
253 && defined(PT_SETDBREGS)
254 #define HAVE_DBREGS
255 #endif
256
257 /*
258 * If waitid(2) returns because one or more processes have a state change to
259 * report, 0 is returned. If an error is detected, a value of -1 is returned
260 * and errno is set to indicate the error. If WNOHANG is specified and there
261 * are no stopped, continued or exited children, 0 is returned.
262 */
263 #if defined(TWAIT_WAITID)
264 #define TWAIT_REQUIRE_SUCCESS(a,b) TEST_REQUIRE_EQ((a), 0)
265 #define TWAIT_REQUIRE_FAILURE(a,b) ATF_REQUIRE_ERRNO((a),(b) == -1)
266 #define FORKEE_REQUIRE_SUCCESS(a,b) FORKEE_ASSERT_EQ(a, 0)
267 #define FORKEE_REQUIRE_FAILURE(a,b) \
268 FORKEE_ASSERTX(((a) == errno) && ((b) == -1))
269 #else
270 #define TWAIT_REQUIRE_SUCCESS(a,b) TEST_REQUIRE_EQ((a), (b))
271 #define TWAIT_REQUIRE_FAILURE(a,b) ATF_REQUIRE_ERRNO((a),(b) == -1)
272 #define FORKEE_REQUIRE_SUCCESS(a,b) FORKEE_ASSERT_EQ(a, b)
273 #define FORKEE_REQUIRE_FAILURE(a,b) \
274 FORKEE_ASSERTX(((a) == errno) && ((b) == -1))
275 #endif
276
277 /*
278 * Helper tools to verify whether status reports exited value
279 */
280 #if TWAIT_HAVE_STATUS
281 static void __used
282 validate_status_exited(int status, int expected)
283 {
284 ATF_REQUIRE_MSG(WIFEXITED(status), "Reported !exited process");
285 ATF_REQUIRE_MSG(!WIFCONTINUED(status), "Reported continued process");
286 ATF_REQUIRE_MSG(!WIFSIGNALED(status), "Reported signaled process");
287 ATF_REQUIRE_MSG(!WIFSTOPPED(status), "Reported stopped process");
288
289 ATF_REQUIRE_EQ_MSG(WEXITSTATUS(status), expected,
290 "The process has exited with invalid value %d != %d",
291 WEXITSTATUS(status), expected);
292 }
293
294 static void __used
295 forkee_status_exited(int status, int expected)
296 {
297 FORKEE_ASSERTX(WIFEXITED(status));
298 FORKEE_ASSERTX(!WIFCONTINUED(status));
299 FORKEE_ASSERTX(!WIFSIGNALED(status));
300 FORKEE_ASSERTX(!WIFSTOPPED(status));
301
302 FORKEE_ASSERT_EQ(WEXITSTATUS(status), expected);
303 }
304
305 static void __used
306 validate_status_continued(int status)
307 {
308 ATF_REQUIRE_MSG(!WIFEXITED(status), "Reported exited process");
309 ATF_REQUIRE_MSG(WIFCONTINUED(status), "Reported !continued process");
310 ATF_REQUIRE_MSG(!WIFSIGNALED(status), "Reported signaled process");
311 ATF_REQUIRE_MSG(!WIFSTOPPED(status), "Reported stopped process");
312 }
313
314 static void __used
315 forkee_status_continued(int status)
316 {
317 FORKEE_ASSERTX(!WIFEXITED(status));
318 FORKEE_ASSERTX(WIFCONTINUED(status));
319 FORKEE_ASSERTX(!WIFSIGNALED(status));
320 FORKEE_ASSERTX(!WIFSTOPPED(status));
321 }
322
323 static void __used
324 validate_status_signaled(int status, int expected_termsig, int expected_core)
325 {
326 ATF_REQUIRE_MSG(!WIFEXITED(status), "Reported exited process");
327 ATF_REQUIRE_MSG(!WIFCONTINUED(status), "Reported continued process");
328 ATF_REQUIRE_MSG(WIFSIGNALED(status), "Reported !signaled process");
329 ATF_REQUIRE_MSG(!WIFSTOPPED(status), "Reported stopped process");
330
331 ATF_REQUIRE_EQ_MSG(WTERMSIG(status), expected_termsig,
332 "Unexpected signal received");
333
334 ATF_REQUIRE_EQ_MSG(!!WCOREDUMP(status), expected_core,
335 "Unexpectedly core file %s generated", expected_core ? "not" : "");
336 }
337
338 static void __used
339 forkee_status_signaled(int status, int expected_termsig, int expected_core)
340 {
341 FORKEE_ASSERTX(!WIFEXITED(status));
342 FORKEE_ASSERTX(!WIFCONTINUED(status));
343 FORKEE_ASSERTX(WIFSIGNALED(status));
344 FORKEE_ASSERTX(!WIFSTOPPED(status));
345
346 FORKEE_ASSERT_EQ(WTERMSIG(status), expected_termsig);
347 FORKEE_ASSERT_EQ(!!WCOREDUMP(status), expected_core);
348 }
349
350 static void __used
351 validate_status_stopped(int status, int expected)
352 {
353 ATF_REQUIRE_MSG(!WIFEXITED(status), "Reported exited process");
354 ATF_REQUIRE_MSG(!WIFCONTINUED(status), "Reported continued process");
355 ATF_REQUIRE_MSG(!WIFSIGNALED(status), "Reported signaled process");
356 ATF_REQUIRE_MSG(WIFSTOPPED(status), "Reported !stopped process");
357
358 char st[128], ex[128];
359 strlcpy(st, strsignal(WSTOPSIG(status)), sizeof(st));
360 strlcpy(ex, strsignal(expected), sizeof(ex));
361
362 ATF_REQUIRE_EQ_MSG(WSTOPSIG(status), expected,
363 "Unexpected stop signal received [%s] != [%s]", st, ex);
364 }
365
366 static void __used
367 forkee_status_stopped(int status, int expected)
368 {
369 FORKEE_ASSERTX(!WIFEXITED(status));
370 FORKEE_ASSERTX(!WIFCONTINUED(status));
371 FORKEE_ASSERTX(!WIFSIGNALED(status));
372 FORKEE_ASSERTX(WIFSTOPPED(status));
373
374 FORKEE_ASSERT_EQ(WSTOPSIG(status), expected);
375 }
376 #else
377 #define validate_status_exited(a,b)
378 #define forkee_status_exited(a,b)
379 #define validate_status_continued(a,b)
380 #define forkee_status_continued(a,b)
381 #define validate_status_signaled(a,b,c)
382 #define forkee_status_signaled(a,b,c)
383 #define validate_status_stopped(a,b)
384 #define forkee_status_stopped(a,b)
385 #endif
386
387 /* This function is currently designed to be run in the main/parent process */
388 static void __used
389 await_zombie_raw(pid_t process, useconds_t ms)
390 {
391 struct kinfo_proc2 p;
392 size_t len = sizeof(p);
393
394 const int name[] = {
395 [0] = CTL_KERN,
396 [1] = KERN_PROC2,
397 [2] = KERN_PROC_PID,
398 [3] = process,
399 [4] = sizeof(p),
400 [5] = 1
401 };
402
403 const size_t namelen = __arraycount(name);
404
405 /* Await the process becoming a zombie */
406 while(1) {
407 ATF_REQUIRE(sysctl(name, namelen, &p, &len, NULL, 0) == 0);
408
409 if (p.p_stat == LSZOMB)
410 break;
411
412 if (ms > 0) {
413 ATF_REQUIRE(usleep(ms) == 0);
414 }
415 }
416 }
417
418 static void __used
419 await_zombie(pid_t process)
420 {
421
422 await_zombie_raw(process, 1000);
423 }
424
425 static void __used
426 await_stopped(pid_t process)
427 {
428 struct kinfo_proc2 p;
429 size_t len = sizeof(p);
430
431 const int name[] = {
432 [0] = CTL_KERN,
433 [1] = KERN_PROC2,
434 [2] = KERN_PROC_PID,
435 [3] = process,
436 [4] = sizeof(p),
437 [5] = 1
438 };
439
440 const size_t namelen = __arraycount(name);
441
442 /* Await the process becoming a zombie */
443 while(1) {
444 ATF_REQUIRE(sysctl(name, namelen, &p, &len, NULL, 0) == 0);
445
446 if (p.p_stat == LSSTOP)
447 break;
448
449 ATF_REQUIRE(usleep(1000) == 0);
450 }
451 }
452
453 static pid_t __used
454 await_stopped_child(pid_t process)
455 {
456 struct kinfo_proc2 *p = NULL;
457 size_t i, len;
458 pid_t child = -1;
459
460 int name[] = {
461 [0] = CTL_KERN,
462 [1] = KERN_PROC2,
463 [2] = KERN_PROC_ALL,
464 [3] = 0,
465 [4] = sizeof(struct kinfo_proc2),
466 [5] = 0
467 };
468
469 const size_t namelen = __arraycount(name);
470
471 /* Await the process becoming a zombie */
472 while(1) {
473 name[5] = 0;
474
475 FORKEE_ASSERT_EQ(sysctl(name, namelen, 0, &len, NULL, 0), 0);
476
477 FORKEE_ASSERT_EQ(reallocarr(&p,
478 len,
479 sizeof(struct kinfo_proc2)), 0);
480
481 name[5] = len;
482
483 FORKEE_ASSERT_EQ(sysctl(name, namelen, p, &len, NULL, 0), 0);
484
485 for (i = 0; i < len/sizeof(struct kinfo_proc2); i++) {
486 if (p[i].p_pid == getpid())
487 continue;
488 if (p[i].p_ppid != process)
489 continue;
490 if (p[i].p_stat != LSSTOP)
491 continue;
492 child = p[i].p_pid;
493 break;
494 }
495
496 if (child != -1)
497 break;
498
499 FORKEE_ASSERT_EQ(usleep(1000), 0);
500 }
501
502 /* Free the buffer */
503 FORKEE_ASSERT_EQ(reallocarr(&p, 0, sizeof(struct kinfo_proc2)), 0);
504
505 return child;
506 }
507
508 static void __used
509 await_collected(pid_t process)
510 {
511 struct kinfo_proc2 p;
512 size_t len = sizeof(p);
513
514 const int name[] = {
515 [0] = CTL_KERN,
516 [1] = KERN_PROC2,
517 [2] = KERN_PROC_PID,
518 [3] = process,
519 [4] = sizeof(p),
520 [5] = 1
521 };
522
523 const size_t namelen = __arraycount(name);
524
525 /* Await the process to disappear */
526 while(1) {
527 FORKEE_ASSERT_EQ(sysctl(name, namelen, &p, &len, NULL, 0), 0);
528 if (len == 0)
529 break;
530
531 ATF_REQUIRE(usleep(1000) == 0);
532 }
533 }
534
535 /* Happy number sequence -- this function is used to just consume cpu cycles */
536 #define HAPPY_NUMBER 1
537
538 /* If n is not happy then its sequence ends in the cycle:
539 * 4, 16, 37, 58, 89, 145, 42, 20, 4, ... */
540 #define SAD_NUMBER 4
541
542 /* Calculate the sum of the squares of the digits of n */
543 static unsigned __used
544 dsum(unsigned n)
545 {
546 unsigned sum, x;
547 for (sum = 0; n; n /= 10) {
548 x = n % 10;
549 sum += x * x;
550 }
551 return sum;
552 }
553
554 /*
555 * XXX: Disabled optimization is required to make tests for hardware assisted
556 * traps in .text functional
557 *
558 * Tested with GCC 5.4 on NetBSD 7.99.47 amd64
559 */
560 static int __used
561 #ifdef __clang__
562 __attribute__((__optnone__))
563 #else
564 __attribute__((__optimize__("O0")))
565 #endif
566 check_happy(unsigned n)
567 {
568 for (;;) {
569 unsigned total = dsum(n);
570
571 if (total == HAPPY_NUMBER)
572 return 1;
573 if (total == SAD_NUMBER)
574 return 0;
575
576 n = total;
577 }
578 }
579
580 static void * __used
581 infinite_thread(void *arg __unused)
582 {
583
584 while (true)
585 continue;
586
587 __unreachable();
588 }
589
590 static int __used
591 clone_func(void *arg)
592 {
593 int ret;
594
595 ret = (int)(intptr_t)arg;
596
597 return ret;
598 }
599
600 #if defined(HAVE_DBREGS)
601 static bool __used
602 can_we_set_dbregs(void)
603 {
604 static long euid = -1;
605 static int user_set_dbregs = -1;
606 size_t user_set_dbregs_len = sizeof(user_set_dbregs);
607
608 if (euid == -1)
609 euid = geteuid();
610
611 if (euid == 0)
612 return true;
613
614 if (user_set_dbregs == -1) {
615 if (sysctlbyname("security.models.extensions.user_set_dbregs",
616 &user_set_dbregs, &user_set_dbregs_len, NULL, 0)
617 == -1) {
618 return false;
619 }
620 }
621
622 if (user_set_dbregs > 0)
623 return true;
624 else
625 return false;
626 }
627 #endif
628
629 static bool __used
630 get_user_va0_disable(void)
631 {
632 static int user_va0_disable = -1;
633 size_t user_va0_disable_len = sizeof(user_va0_disable);
634
635 if (user_va0_disable == -1) {
636 if (sysctlbyname("vm.user_va0_disable",
637 &user_va0_disable, &user_va0_disable_len, NULL, 0)
638 == -1) {
639 return true;
640 }
641 }
642
643 if (user_va0_disable > 0)
644 return true;
645 else
646 return false;
647 }
648
649 static bool __used
650 can_we_write_to_text(pid_t pid)
651 {
652 int mib[3];
653 int paxflags;
654 size_t len = sizeof(int);
655
656 mib[0] = CTL_PROC;
657 mib[1] = pid;
658 mib[2] = PROC_PID_PAXFLAGS;
659
660 if (sysctl(mib, 3, &paxflags, &len, NULL, 0) == -1)
661 return false;
662
663 return !(paxflags & CTL_PROC_PAXFLAGS_MPROTECT);
664 }
665
666 static void __used
667 trigger_trap(void)
668 {
669
670 /* Software breakpoint causes CPU trap, translated to SIGTRAP */
671 #ifdef PTRACE_BREAKPOINT_ASM
672 PTRACE_BREAKPOINT_ASM;
673 #else
674 /* port me */
675 #endif
676 }
677
678 static void __used
679 trigger_segv(void)
680 {
681 static volatile char *ptr = NULL;
682
683 /* Access to unmapped memory causes CPU trap, translated to SIGSEGV */
684 *ptr = 1;
685 }
686
687 static void __used
688 trigger_ill(void)
689 {
690
691 /* Illegal instruction causes CPU trap, translated to SIGILL */
692 #ifdef PTRACE_ILLEGAL_ASM
693 #ifndef __mips__ /* To avoid GXemul crash */
694 PTRACE_ILLEGAL_ASM;
695 #endif
696 #else
697 /* port me */
698 #endif
699 }
700
701 #include <fenv.h>
702
703 #if (__arm__ && !__SOFTFP__) || __aarch64__
704 #include <ieeefp.h> /* only need for ARM Cortex/Neon hack */
705
706 static bool __used
707 are_fpu_exceptions_supported(void)
708 {
709 /*
710 * Some NEON fpus do not trap on IEEE 754 FP exceptions.
711 * Skip these tests if running on them and compiled for
712 * hard float.
713 */
714 if (0 == fpsetmask(fpsetmask(FP_X_INV)))
715 return false;
716 return true;
717 }
718 #elif defined __riscv__
719 #define are_fpu_exceptions_supported() 0
720 #else
721 #define are_fpu_exceptions_supported() 1
722 #endif
723
724 volatile double ignore_result;
725
726 static void __used
727 trigger_fpe(void)
728 {
729 #if __i386__ || __x86_64__
730 /*
731 * XXX
732 * Hack for QEMU bug #1668041, by which floating-point division by
733 * zero is not trapped correctly. Also, assertions for si_code in
734 * ptrace_signal_wait.h are commented out. Clean them up after the
735 * bug is fixed.
736 */
737 volatile int a, b;
738 #else
739 volatile double a, b;
740 #endif
741
742 a = getpid();
743 b = atoi("0");
744
745 #ifdef __HAVE_FENV
746 feenableexcept(FE_ALL_EXCEPT);
747 #endif
748
749 /* Division by zero causes CPU trap, translated to SIGFPE */
750 ignore_result = (int)(a / b);
751 }
752
753 static void __used
754 trigger_bus(void)
755 {
756 FILE *fp;
757 char *p;
758
759 /* Open an empty file for writing. */
760 fp = tmpfile();
761 FORKEE_ASSERT_NEQ((uintptr_t)fp, (uintptr_t)NULL);
762
763 /*
764 * Map an empty file with mmap(2) to a pointer.
765 *
766 * PROT_READ handles read-modify-write sequences emitted for
767 * certain combinations of CPUs and compilers (e.g. Alpha AXP).
768 */
769 p = mmap(0, 1, PROT_READ|PROT_WRITE, MAP_PRIVATE, fileno(fp), 0);
770 FORKEE_ASSERT_NEQ((uintptr_t)p, (uintptr_t)MAP_FAILED);
771
772 /* Invalid memory access causes CPU trap, translated to SIGBUS */
773 *p = 'a';
774 }
775
776 struct lwp_event_count {
777 lwpid_t lec_lwp;
778 int lec_count;
779 };
780
781 static int * __used
782 find_event_count(struct lwp_event_count list[], lwpid_t lwp, size_t max_lwps)
783 {
784 size_t i;
785
786 for (i = 0; i < max_lwps; i++) {
787 if (list[i].lec_lwp == 0)
788 list[i].lec_lwp = lwp;
789 if (list[i].lec_lwp == lwp)
790 return &list[i].lec_count;
791 }
792
793 atf_tc_fail("More LWPs reported than expected");
794 }
795
796 #define FIND_EVENT_COUNT(list, lwp) \
797 find_event_count(list, lwp, __arraycount(list))
798
799 #if defined(TWAIT_HAVE_PID)
800 #define ATF_TP_ADD_TC_HAVE_PID(a,b) ATF_TP_ADD_TC(a,b)
801 #else
802 #define ATF_TP_ADD_TC_HAVE_PID(a,b)
803 #endif
804
805 #if defined(TWAIT_HAVE_STATUS)
806 #define ATF_TP_ADD_TC_HAVE_STATUS(a,b) ATF_TP_ADD_TC(a,b)
807 #else
808 #define ATF_TP_ADD_TC_HAVE_STATUS(a,b)
809 #endif
810
811 #if defined(TWAIT_HAVE_STATUS) && (defined(__i386__) || defined(__x86_64__))
812 #define ATF_TP_ADD_TC_HAVE_STATUS_X86(a,b) ATF_TP_ADD_TC(a,b)
813 #else
814 #define ATF_TP_ADD_TC_HAVE_STATUS_X86(a,b)
815 #endif
816
817 #if defined(HAVE_GPREGS)
818 #define ATF_TP_ADD_TC_HAVE_GPREGS(a,b) ATF_TP_ADD_TC(a,b)
819 #else
820 #define ATF_TP_ADD_TC_HAVE_GPREGS(a,b)
821 #endif
822
823 #if defined(HAVE_FPREGS)
824 #define ATF_TP_ADD_TC_HAVE_FPREGS(a,b) ATF_TP_ADD_TC(a,b)
825 #else
826 #define ATF_TP_ADD_TC_HAVE_FPREGS(a,b)
827 #endif
828
829 #if defined(HAVE_DBREGS)
830 #define ATF_TP_ADD_TC_HAVE_DBREGS(a,b) ATF_TP_ADD_TC(a,b)
831 #else
832 #define ATF_TP_ADD_TC_HAVE_DBREGS(a,b)
833 #endif
834
835 #if defined(PT_STEP)
836 #define ATF_TP_ADD_TC_PT_STEP(a,b) ATF_TP_ADD_TC(a,b)
837 #else
838 #define ATF_TP_ADD_TC_PT_STEP(a,b)
839 #endif
840