Home | History | Annotate | Line # | Download | only in sys
t_ptrace_clone_wait.h revision 1.4
      1 /*	$NetBSD: t_ptrace_clone_wait.h,v 1.4 2025/05/02 02:24:32 riastradh Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 2016, 2017, 2018, 2019, 2020 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 static void
     30 clone_body(int flags, bool trackfork, bool trackvfork,
     31     bool trackvforkdone)
     32 {
     33 	const int exitval = 5;
     34 	const int exitval2 = 15;
     35 	const int sigval = SIGSTOP;
     36 	pid_t child, child2 = 0, wpid;
     37 #if defined(TWAIT_HAVE_STATUS)
     38 	int status;
     39 #endif
     40 	ptrace_state_t state;
     41 	const int slen = sizeof(state);
     42 	ptrace_event_t event;
     43 	const int elen = sizeof(event);
     44 
     45 	const size_t stack_size = 1024 * 1024;
     46 	void *stack, *stack_base;
     47 
     48 	stack = malloc(stack_size);
     49 	ATF_REQUIRE(stack != NULL);
     50 
     51 #ifdef __MACHINE_STACK_GROWS_UP
     52 	stack_base = stack;
     53 #else
     54 	stack_base = (char *)stack + stack_size;
     55 #endif
     56 
     57 	DPRINTF("Before forking process PID=%d\n", getpid());
     58 	SYSCALL_REQUIRE((child = fork()) != -1);
     59 	if (child == 0) {
     60 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
     61 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
     62 
     63 		DPRINTF("Before raising %s from child\n", strsignal(sigval));
     64 		FORKEE_ASSERT(raise(sigval) == 0);
     65 
     66 		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
     67 		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
     68 
     69 		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
     70 		    child2);
     71 
     72 		// XXX WALLSIG?
     73 		FORKEE_REQUIRE_SUCCESS
     74 		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
     75 
     76 		forkee_status_exited(status, exitval2);
     77 
     78 		DPRINTF("Before exiting of the child process\n");
     79 		_exit(exitval);
     80 	}
     81 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
     82 
     83 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
     84 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
     85 
     86 	validate_status_stopped(status, sigval);
     87 
     88 	DPRINTF("Set 0%s%s%s in EVENT_MASK for the child %d\n",
     89 	    trackfork ? "|PTRACE_FORK" : "",
     90 	    trackvfork ? "|PTRACE_VFORK" : "",
     91 	    trackvforkdone ? "|PTRACE_VFORK_DONE" : "", child);
     92 	event.pe_set_event = 0;
     93 	if (trackfork)
     94 		event.pe_set_event |= PTRACE_FORK;
     95 	if (trackvfork)
     96 		event.pe_set_event |= PTRACE_VFORK;
     97 	if (trackvforkdone)
     98 		event.pe_set_event |= PTRACE_VFORK_DONE;
     99 	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
    100 
    101 	DPRINTF("Before resuming the child process where it left off and "
    102 	    "without signal to be sent\n");
    103 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
    104 
    105 #if defined(TWAIT_HAVE_PID)
    106 	if ((trackfork && !(flags & CLONE_VFORK)) ||
    107 	    (trackvfork && (flags & CLONE_VFORK))) {
    108 		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
    109 		    child);
    110 		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
    111 		    child);
    112 
    113 		validate_status_stopped(status, SIGTRAP);
    114 
    115 		SYSCALL_REQUIRE(
    116 		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
    117 		if (trackfork && !(flags & CLONE_VFORK)) {
    118 			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
    119 			       PTRACE_FORK);
    120 		}
    121 		if (trackvfork && (flags & CLONE_VFORK)) {
    122 			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
    123 			       PTRACE_VFORK);
    124 		}
    125 
    126 		child2 = state.pe_other_pid;
    127 		DPRINTF("Reported ptrace event with forkee %d\n", child2);
    128 
    129 		DPRINTF("Before calling %s() for the forkee %d of the child "
    130 		    "%d\n", TWAIT_FNAME, child2, child);
    131 		TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
    132 		    child2);
    133 
    134 		validate_status_stopped(status, SIGTRAP);
    135 
    136 		SYSCALL_REQUIRE(
    137 		    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
    138 		if (trackfork && !(flags & CLONE_VFORK)) {
    139 			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
    140 			       PTRACE_FORK);
    141 		}
    142 		if (trackvfork && (flags & CLONE_VFORK)) {
    143 			ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
    144 			       PTRACE_VFORK);
    145 		}
    146 
    147 		ATF_REQUIRE_EQ(state.pe_other_pid, child);
    148 
    149 		DPRINTF("Before resuming the forkee process where it left off "
    150 		    "and without signal to be sent\n");
    151 		SYSCALL_REQUIRE(
    152 		    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
    153 
    154 		DPRINTF("Before resuming the child process where it left off "
    155 		    "and without signal to be sent\n");
    156 		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
    157 	}
    158 #endif
    159 
    160 	if (trackvforkdone && (flags & CLONE_VFORK)) {
    161 		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
    162 		    child);
    163 		TWAIT_REQUIRE_SUCCESS(
    164 		    wpid = TWAIT_GENERIC(child, &status, 0), child);
    165 
    166 		validate_status_stopped(status, SIGTRAP);
    167 
    168 		SYSCALL_REQUIRE(
    169 		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
    170 		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
    171 
    172 		child2 = state.pe_other_pid;
    173 		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
    174 		    child2);
    175 
    176 		DPRINTF("Before resuming the child process where it left off "
    177 		    "and without signal to be sent\n");
    178 		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
    179 	}
    180 
    181 #if defined(TWAIT_HAVE_PID)
    182 	if ((trackfork && !(flags & CLONE_VFORK)) ||
    183 	    (trackvfork && (flags & CLONE_VFORK))) {
    184 		DPRINTF("Before calling %s() for the forkee - expected exited"
    185 		    "\n", TWAIT_FNAME);
    186 		TWAIT_REQUIRE_SUCCESS(
    187 		    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
    188 
    189 		validate_status_exited(status, exitval2);
    190 
    191 		DPRINTF("Before calling %s() for the forkee - expected no "
    192 		    "process\n", TWAIT_FNAME);
    193 		TWAIT_REQUIRE_FAILURE(ECHILD,
    194 		    wpid = TWAIT_GENERIC(child2, &status, 0));
    195 	}
    196 #endif
    197 
    198 	DPRINTF("Before calling %s() for the child - expected stopped "
    199 	    "SIGCHLD\n", TWAIT_FNAME);
    200 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
    201 
    202 	validate_status_stopped(status, SIGCHLD);
    203 
    204 	DPRINTF("Before resuming the child process where it left off and "
    205 	    "without signal to be sent\n");
    206 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
    207 
    208 	DPRINTF("Before calling %s() for the child - expected exited\n",
    209 	    TWAIT_FNAME);
    210 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
    211 
    212 	validate_status_exited(status, exitval);
    213 
    214 	DPRINTF("Before calling %s() for the child - expected no process\n",
    215 	    TWAIT_FNAME);
    216 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
    217 }
    218 
    219 #define CLONE_TEST(name,flags,tfork,tvfork,tvforkdone)			\
    220 ATF_TC(name);								\
    221 ATF_TC_HEAD(name, tc)							\
    222 {									\
    223 	atf_tc_set_md_var(tc, "descr", "Verify clone(%s) "		\
    224 	    "called with 0%s%s%s in EVENT_MASK",			\
    225 	    #flags,							\
    226 	    tfork ? "|PTRACE_FORK" : "",				\
    227 	    tvfork ? "|PTRACE_VFORK" : "",				\
    228 	    tvforkdone ? "|PTRACE_VFORK_DONE" : "");			\
    229 }									\
    230 									\
    231 ATF_TC_BODY(name, tc)							\
    232 {									\
    233 									\
    234 	clone_body(flags, tfork, tvfork, tvforkdone);			\
    235 }
    236 
    237 CLONE_TEST(clone1, 0, false, false, false)
    238 #if defined(TWAIT_HAVE_PID)
    239 CLONE_TEST(clone2, 0, true, false, false)
    240 CLONE_TEST(clone3, 0, false, true, false)
    241 CLONE_TEST(clone4, 0, true, true, false)
    242 #endif
    243 CLONE_TEST(clone5, 0, false, false, true)
    244 #if defined(TWAIT_HAVE_PID)
    245 CLONE_TEST(clone6, 0, true, false, true)
    246 CLONE_TEST(clone7, 0, false, true, true)
    247 CLONE_TEST(clone8, 0, true, true, true)
    248 #endif
    249 
    250 CLONE_TEST(clone_vm1, CLONE_VM, false, false, false)
    251 #if defined(TWAIT_HAVE_PID)
    252 CLONE_TEST(clone_vm2, CLONE_VM, true, false, false)
    253 CLONE_TEST(clone_vm3, CLONE_VM, false, true, false)
    254 CLONE_TEST(clone_vm4, CLONE_VM, true, true, false)
    255 #endif
    256 CLONE_TEST(clone_vm5, CLONE_VM, false, false, true)
    257 #if defined(TWAIT_HAVE_PID)
    258 CLONE_TEST(clone_vm6, CLONE_VM, true, false, true)
    259 CLONE_TEST(clone_vm7, CLONE_VM, false, true, true)
    260 CLONE_TEST(clone_vm8, CLONE_VM, true, true, true)
    261 #endif
    262 
    263 CLONE_TEST(clone_fs1, CLONE_FS, false, false, false)
    264 #if defined(TWAIT_HAVE_PID)
    265 CLONE_TEST(clone_fs2, CLONE_FS, true, false, false)
    266 CLONE_TEST(clone_fs3, CLONE_FS, false, true, false)
    267 CLONE_TEST(clone_fs4, CLONE_FS, true, true, false)
    268 #endif
    269 CLONE_TEST(clone_fs5, CLONE_FS, false, false, true)
    270 #if defined(TWAIT_HAVE_PID)
    271 CLONE_TEST(clone_fs6, CLONE_FS, true, false, true)
    272 CLONE_TEST(clone_fs7, CLONE_FS, false, true, true)
    273 CLONE_TEST(clone_fs8, CLONE_FS, true, true, true)
    274 #endif
    275 
    276 CLONE_TEST(clone_files1, CLONE_FILES, false, false, false)
    277 #if defined(TWAIT_HAVE_PID)
    278 CLONE_TEST(clone_files2, CLONE_FILES, true, false, false)
    279 CLONE_TEST(clone_files3, CLONE_FILES, false, true, false)
    280 CLONE_TEST(clone_files4, CLONE_FILES, true, true, false)
    281 #endif
    282 CLONE_TEST(clone_files5, CLONE_FILES, false, false, true)
    283 #if defined(TWAIT_HAVE_PID)
    284 CLONE_TEST(clone_files6, CLONE_FILES, true, false, true)
    285 CLONE_TEST(clone_files7, CLONE_FILES, false, true, true)
    286 CLONE_TEST(clone_files8, CLONE_FILES, true, true, true)
    287 #endif
    288 
    289 //CLONE_TEST(clone_sighand1, CLONE_SIGHAND, false, false, false)
    290 #if defined(TWAIT_HAVE_PID)
    291 //CLONE_TEST(clone_sighand2, CLONE_SIGHAND, true, false, false)
    292 //CLONE_TEST(clone_sighand3, CLONE_SIGHAND, false, true, false)
    293 //CLONE_TEST(clone_sighand4, CLONE_SIGHAND, true, true, false)
    294 #endif
    295 //CLONE_TEST(clone_sighand5, CLONE_SIGHAND, false, false, true)
    296 #if defined(TWAIT_HAVE_PID)
    297 //CLONE_TEST(clone_sighand6, CLONE_SIGHAND, true, false, true)
    298 //CLONE_TEST(clone_sighand7, CLONE_SIGHAND, false, true, true)
    299 //CLONE_TEST(clone_sighand8, CLONE_SIGHAND, true, true, true)
    300 #endif
    301 
    302 CLONE_TEST(clone_vfork1, CLONE_VFORK, false, false, false)
    303 #if defined(TWAIT_HAVE_PID)
    304 CLONE_TEST(clone_vfork2, CLONE_VFORK, true, false, false)
    305 CLONE_TEST(clone_vfork3, CLONE_VFORK, false, true, false)
    306 CLONE_TEST(clone_vfork4, CLONE_VFORK, true, true, false)
    307 #endif
    308 CLONE_TEST(clone_vfork5, CLONE_VFORK, false, false, true)
    309 #if defined(TWAIT_HAVE_PID)
    310 CLONE_TEST(clone_vfork6, CLONE_VFORK, true, false, true)
    311 CLONE_TEST(clone_vfork7, CLONE_VFORK, false, true, true)
    312 CLONE_TEST(clone_vfork8, CLONE_VFORK, true, true, true)
    313 #endif
    314 
    315 /// ----------------------------------------------------------------------------
    316 
    317 #if defined(TWAIT_HAVE_PID)
    318 static void
    319 clone_body2(int flags, bool masked, bool ignored)
    320 {
    321 	const int exitval = 5;
    322 	const int exitval2 = 15;
    323 	const int sigval = SIGSTOP;
    324 	pid_t child, child2 = 0, wpid;
    325 #if defined(TWAIT_HAVE_STATUS)
    326 	int status;
    327 #endif
    328 	ptrace_state_t state;
    329 	const int slen = sizeof(state);
    330 	ptrace_event_t event;
    331 	const int elen = sizeof(event);
    332 	struct sigaction sa;
    333 	struct ptrace_siginfo info;
    334 	sigset_t intmask;
    335 	struct kinfo_proc2 kp;
    336 	size_t len = sizeof(kp);
    337 
    338 	int name[6];
    339 	const size_t namelen = __arraycount(name);
    340 	ki_sigset_t kp_sigmask;
    341 	ki_sigset_t kp_sigignore;
    342 
    343 	const size_t stack_size = 1024 * 1024;
    344 	void *stack, *stack_base;
    345 
    346 	stack = malloc(stack_size);
    347 	ATF_REQUIRE(stack != NULL);
    348 
    349 #ifdef __MACHINE_STACK_GROWS_UP
    350 	stack_base = stack;
    351 #else
    352 	stack_base = (char *)stack + stack_size;
    353 #endif
    354 
    355 	SYSCALL_REQUIRE((child = fork()) != -1);
    356 	if (child == 0) {
    357 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
    358 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
    359 
    360 		if (masked) {
    361 			sigemptyset(&intmask);
    362 			sigaddset(&intmask, SIGTRAP);
    363 			sigprocmask(SIG_BLOCK, &intmask, NULL);
    364 		}
    365 
    366 		if (ignored) {
    367 			memset(&sa, 0, sizeof(sa));
    368 			sa.sa_handler = SIG_IGN;
    369 			sigemptyset(&sa.sa_mask);
    370 			FORKEE_ASSERT(sigaction(SIGTRAP, &sa, NULL) != -1);
    371 		}
    372 		DPRINTF("Before raising %s from child\n", strsignal(sigval));
    373 		FORKEE_ASSERT(raise(sigval) == 0);
    374 
    375 		DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(),
    376 		    flags);
    377 		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
    378 		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
    379 
    380 		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
    381 		    child2);
    382 
    383 		// XXX WALLSIG?
    384 		FORKEE_REQUIRE_SUCCESS
    385 		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
    386 
    387 		forkee_status_exited(status, exitval2);
    388 
    389 		DPRINTF("Before exiting of the child process\n");
    390 		_exit(exitval);
    391 	}
    392 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
    393 
    394 	DPRINTF("Before calling %s() for the child\n", TWAIT_FNAME);
    395 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
    396 
    397 	validate_status_stopped(status, sigval);
    398 
    399 	DPRINTF("Before calling ptrace(2) with PT_GET_SIGINFO for child\n");
    400 	SYSCALL_REQUIRE(
    401 	    ptrace(PT_GET_SIGINFO, child, &info, sizeof(info)) != -1);
    402 
    403 	DPRINTF("Before checking siginfo_t\n");
    404 	ATF_REQUIRE_EQ(info.psi_siginfo.si_signo, sigval);
    405 	ATF_REQUIRE_EQ(info.psi_siginfo.si_code, SI_LWP);
    406 
    407 	name[0] = CTL_KERN,
    408 	name[1] = KERN_PROC2,
    409 	name[2] = KERN_PROC_PID;
    410 	name[3] = child;
    411 	name[4] = sizeof(kp);
    412 	name[5] = 1;
    413 
    414 	FORKEE_ASSERT_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
    415 
    416 	kp_sigmask = kp.p_sigmask;
    417 	kp_sigignore = kp.p_sigignore;
    418 
    419 	DPRINTF("Set PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE in "
    420 	    "EVENT_MASK for the child %d\n", child);
    421 	event.pe_set_event = PTRACE_FORK | PTRACE_VFORK | PTRACE_VFORK_DONE;
    422 	SYSCALL_REQUIRE(ptrace(PT_SET_EVENT_MASK, child, &event, elen) != -1);
    423 
    424 	DPRINTF("Before resuming the child process where it left off and "
    425 	    "without signal to be sent\n");
    426 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
    427 
    428 	DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
    429 	    child);
    430 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0),
    431 	    child);
    432 
    433 	validate_status_stopped(status, SIGTRAP);
    434 
    435 	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
    436 
    437 	if (masked) {
    438 		DPRINTF("kp_sigmask="
    439 		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
    440 		    PRIx32 "\n",
    441 		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
    442 		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
    443 
    444 		DPRINTF("kp.p_sigmask="
    445 		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
    446 		    PRIx32 "\n",
    447 		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
    448 		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
    449 
    450 		ATF_REQUIRE(sigismember((sigset_t *)&kp.p_sigmask,
    451 			    SIGTRAP));
    452 	}
    453 
    454 	if (ignored) {
    455 		DPRINTF("kp_sigignore="
    456 		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
    457 		    PRIx32 "\n",
    458 		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
    459 		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
    460 
    461 		DPRINTF("kp.p_sigignore="
    462 		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
    463 		    PRIx32 "\n",
    464 		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
    465 		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
    466 
    467 		ATF_REQUIRE(sigismember((sigset_t *)&kp.p_sigignore,
    468 			    SIGTRAP));
    469 	}
    470 
    471 	SYSCALL_REQUIRE(
    472 	    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
    473 	DPRINTF("state.pe_report_event=%#x pid=%d\n", state.pe_report_event,
    474 	    child2);
    475 	if (!(flags & CLONE_VFORK)) {
    476 		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
    477 		       PTRACE_FORK);
    478 	} else {
    479 		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
    480 		       PTRACE_VFORK);
    481 	}
    482 
    483 	child2 = state.pe_other_pid;
    484 	DPRINTF("Reported ptrace event with forkee %d\n", child2);
    485 
    486 	DPRINTF("Before calling %s() for the forkee %d of the child "
    487 	    "%d\n", TWAIT_FNAME, child2, child);
    488 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child2, &status, 0),
    489 	    child2);
    490 
    491 	validate_status_stopped(status, SIGTRAP);
    492 
    493 	name[3] = child2;
    494 	ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
    495 
    496 	if (masked) {
    497 		DPRINTF("kp_sigmask="
    498 		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
    499 		    PRIx32 "\n",
    500 		    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
    501 		    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
    502 
    503 		DPRINTF("kp.p_sigmask="
    504 		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
    505 		    PRIx32 "\n",
    506 		    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
    507 		    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
    508 
    509 		ATF_REQUIRE(sigismember((sigset_t *)&kp.p_sigmask,
    510 			    SIGTRAP));
    511 	}
    512 
    513 	if (ignored) {
    514 		DPRINTF("kp_sigignore="
    515 		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
    516 		    PRIx32 "\n",
    517 		    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
    518 		    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
    519 
    520 		DPRINTF("kp.p_sigignore="
    521 		    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
    522 		    PRIx32 "\n",
    523 		    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
    524 		    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
    525 
    526 		ATF_REQUIRE(sigismember((sigset_t *)&kp.p_sigignore,
    527 			    SIGTRAP));
    528 	}
    529 
    530 	SYSCALL_REQUIRE(
    531 	    ptrace(PT_GET_PROCESS_STATE, child2, &state, slen) != -1);
    532 	if (!(flags & CLONE_VFORK)) {
    533 		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_FORK,
    534 		       PTRACE_FORK);
    535 	} else {
    536 		ATF_REQUIRE_EQ(state.pe_report_event & PTRACE_VFORK,
    537 		       PTRACE_VFORK);
    538 	}
    539 
    540 	ATF_REQUIRE_EQ(state.pe_other_pid, child);
    541 
    542 	DPRINTF("Before resuming the forkee process where it left off "
    543 	    "and without signal to be sent\n");
    544 	SYSCALL_REQUIRE(
    545 	    ptrace(PT_CONTINUE, child2, (void *)1, 0) != -1);
    546 
    547 	DPRINTF("Before resuming the child process where it left off "
    548 	    "and without signal to be sent\n");
    549 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
    550 
    551 	if (flags & CLONE_VFORK) {
    552 		DPRINTF("Before calling %s() for the child %d\n", TWAIT_FNAME,
    553 		    child);
    554 		TWAIT_REQUIRE_SUCCESS(
    555 		    wpid = TWAIT_GENERIC(child, &status, 0), child);
    556 
    557 		validate_status_stopped(status, SIGTRAP);
    558 
    559 		name[3] = child;
    560 		ATF_REQUIRE_EQ(sysctl(name, namelen, &kp, &len, NULL, 0), 0);
    561 
    562 		/*
    563 		 * SIGCHLD is now pending in the signal queue and
    564 		 * the kernel presents it to userland as a masked signal.
    565 		 */
    566 		sigdelset((sigset_t *)&kp.p_sigmask, SIGCHLD);
    567 
    568 		if (masked) {
    569 			DPRINTF("kp_sigmask="
    570 			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
    571 			    PRIx32 "\n",
    572 			    kp_sigmask.__bits[0], kp_sigmask.__bits[1],
    573 			    kp_sigmask.__bits[2], kp_sigmask.__bits[3]);
    574 
    575 			DPRINTF("kp.p_sigmask="
    576 			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
    577 			    PRIx32 "\n",
    578 			    kp.p_sigmask.__bits[0], kp.p_sigmask.__bits[1],
    579 			    kp.p_sigmask.__bits[2], kp.p_sigmask.__bits[3]);
    580 
    581 			ATF_REQUIRE(!memcmp(&kp_sigmask, &kp.p_sigmask,
    582 			    sizeof(kp_sigmask)));
    583 		}
    584 
    585 		if (ignored) {
    586 			DPRINTF("kp_sigignore="
    587 			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
    588 			    PRIx32 "\n",
    589 			    kp_sigignore.__bits[0], kp_sigignore.__bits[1],
    590 			    kp_sigignore.__bits[2], kp_sigignore.__bits[3]);
    591 
    592 			DPRINTF("kp.p_sigignore="
    593 			    "%#02" PRIx32 "%02" PRIx32 "%02" PRIx32 "%02"
    594 			    PRIx32 "\n",
    595 			    kp.p_sigignore.__bits[0], kp.p_sigignore.__bits[1],
    596 			    kp.p_sigignore.__bits[2], kp.p_sigignore.__bits[3]);
    597 
    598 			ATF_REQUIRE(!memcmp(&kp_sigignore, &kp.p_sigignore,
    599 			    sizeof(kp_sigignore)));
    600 		}
    601 
    602 		SYSCALL_REQUIRE(
    603 		    ptrace(PT_GET_PROCESS_STATE, child, &state, slen) != -1);
    604 		ATF_REQUIRE_EQ(state.pe_report_event, PTRACE_VFORK_DONE);
    605 
    606 		child2 = state.pe_other_pid;
    607 		DPRINTF("Reported PTRACE_VFORK_DONE event with forkee %d\n",
    608 		    child2);
    609 
    610 		DPRINTF("Before resuming the child process where it left off "
    611 		    "and without signal to be sent\n");
    612 		SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
    613 	}
    614 
    615 	DPRINTF("Before calling %s() for the forkee - expected exited"
    616 	    "\n", TWAIT_FNAME);
    617 	TWAIT_REQUIRE_SUCCESS(
    618 	    wpid = TWAIT_GENERIC(child2, &status, 0), child2);
    619 
    620 	validate_status_exited(status, exitval2);
    621 
    622 	DPRINTF("Before calling %s() for the forkee - expected no "
    623 	    "process\n", TWAIT_FNAME);
    624 	TWAIT_REQUIRE_FAILURE(ECHILD,
    625 	    wpid = TWAIT_GENERIC(child2, &status, 0));
    626 
    627 	DPRINTF("Before calling %s() for the child - expected stopped "
    628 	    "SIGCHLD\n", TWAIT_FNAME);
    629 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
    630 
    631 	validate_status_stopped(status, SIGCHLD);
    632 
    633 	DPRINTF("Before resuming the child process where it left off and "
    634 	    "without signal to be sent\n");
    635 	SYSCALL_REQUIRE(ptrace(PT_CONTINUE, child, (void *)1, 0) != -1);
    636 
    637 	DPRINTF("Before calling %s() for the child - expected exited\n",
    638 	    TWAIT_FNAME);
    639 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
    640 
    641 	validate_status_exited(status, exitval);
    642 
    643 	DPRINTF("Before calling %s() for the child - expected no process\n",
    644 	    TWAIT_FNAME);
    645 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
    646 }
    647 
    648 #define CLONE_TEST2(name,flags,masked,ignored)				\
    649 ATF_TC(name);								\
    650 ATF_TC_HEAD(name, tc)							\
    651 {									\
    652 	atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is caught"\
    653 	    " regardless of signal %s%s", 				\
    654 	    #flags, masked ? "masked" : "", ignored ? "ignored" : "");	\
    655 }									\
    656 									\
    657 ATF_TC_BODY(name, tc)							\
    658 {									\
    659 									\
    660 	clone_body2(flags, masked, ignored);				\
    661 }
    662 
    663 CLONE_TEST2(clone_signalignored, 0, true, false)
    664 CLONE_TEST2(clone_signalmasked, 0, false, true)
    665 CLONE_TEST2(clone_vm_signalignored, CLONE_VM, true, false)
    666 CLONE_TEST2(clone_vm_signalmasked, CLONE_VM, false, true)
    667 CLONE_TEST2(clone_fs_signalignored, CLONE_FS, true, false)
    668 CLONE_TEST2(clone_fs_signalmasked, CLONE_FS, false, true)
    669 CLONE_TEST2(clone_files_signalignored, CLONE_FILES, true, false)
    670 CLONE_TEST2(clone_files_signalmasked, CLONE_FILES, false, true)
    671 //CLONE_TEST2(clone_sighand_signalignored, CLONE_SIGHAND, true, false) // XXX
    672 //CLONE_TEST2(clone_sighand_signalmasked, CLONE_SIGHAND, false, true)  // XXX
    673 CLONE_TEST2(clone_vfork_signalignored, CLONE_VFORK, true, false)
    674 CLONE_TEST2(clone_vfork_signalmasked, CLONE_VFORK, false, true)
    675 #endif
    676 
    677 /// ----------------------------------------------------------------------------
    678 
    679 #if defined(TWAIT_HAVE_PID)
    680 static void
    681 traceme_vfork_clone_body(int flags)
    682 {
    683 	const int exitval = 5;
    684 	const int exitval2 = 15;
    685 	pid_t child, child2 = 0, wpid;
    686 #if defined(TWAIT_HAVE_STATUS)
    687 	int status;
    688 #endif
    689 
    690 	const size_t stack_size = 1024 * 1024;
    691 	void *stack, *stack_base;
    692 
    693 	stack = malloc(stack_size);
    694 	ATF_REQUIRE(stack != NULL);
    695 
    696 #ifdef __MACHINE_STACK_GROWS_UP
    697 	stack_base = stack;
    698 #else
    699 	stack_base = (char *)stack + stack_size;
    700 #endif
    701 
    702 	SYSCALL_REQUIRE((child = vfork()) != -1);
    703 	if (child == 0) {
    704 		DPRINTF("Before calling PT_TRACE_ME from child %d\n", getpid());
    705 		FORKEE_ASSERT(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1);
    706 
    707 		DPRINTF("Before forking process PID=%d flags=%#x\n", getpid(),
    708 		    flags);
    709 		SYSCALL_REQUIRE((child2 = __clone(clone_func, stack_base,
    710 		    flags|SIGCHLD, (void *)(intptr_t)exitval2)) != -1);
    711 
    712 		DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(),
    713 		    child2);
    714 
    715 		// XXX WALLSIG?
    716 		FORKEE_REQUIRE_SUCCESS
    717 		    (wpid = TWAIT_GENERIC(child2, &status, WALLSIG), child2);
    718 
    719 		forkee_status_exited(status, exitval2);
    720 
    721 		DPRINTF("Before exiting of the child process\n");
    722 		_exit(exitval);
    723 	}
    724 	DPRINTF("Parent process PID=%d, child's PID=%d\n", getpid(), child);
    725 
    726 	DPRINTF("Before calling %s() for the child - expected exited\n",
    727 	    TWAIT_FNAME);
    728 	TWAIT_REQUIRE_SUCCESS(wpid = TWAIT_GENERIC(child, &status, 0), child);
    729 
    730 	validate_status_exited(status, exitval);
    731 
    732 	DPRINTF("Before calling %s() for the child - expected no process\n",
    733 	    TWAIT_FNAME);
    734 	TWAIT_REQUIRE_FAILURE(ECHILD, wpid = TWAIT_GENERIC(child, &status, 0));
    735 }
    736 
    737 #define TRACEME_VFORK_CLONE_TEST(name,flags)				\
    738 ATF_TC(name);								\
    739 ATF_TC_HEAD(name, tc)							\
    740 {									\
    741 	atf_tc_set_md_var(tc, "descr", "Verify that clone(%s) is "	\
    742 	    "handled correctly with vfork(2)ed tracer", 		\
    743 	    #flags);							\
    744 }									\
    745 									\
    746 ATF_TC_BODY(name, tc)							\
    747 {									\
    748 									\
    749 	traceme_vfork_clone_body(flags);				\
    750 }
    751 
    752 TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone, 0)
    753 TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vm, CLONE_VM)
    754 TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_fs, CLONE_FS)
    755 TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_files, CLONE_FILES)
    756 //TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_sighand, CLONE_SIGHAND)  // XXX
    757 TRACEME_VFORK_CLONE_TEST(traceme_vfork_clone_vfork, CLONE_VFORK)
    758 #endif
    759 
    760 #define ATF_TP_ADD_TCS_PTRACE_WAIT_CLONE() \
    761 	ATF_TP_ADD_TC(tp, clone1); \
    762 	ATF_TP_ADD_TC_HAVE_PID(tp, clone2); \
    763 	ATF_TP_ADD_TC_HAVE_PID(tp, clone3); \
    764 	ATF_TP_ADD_TC_HAVE_PID(tp, clone4); \
    765 	ATF_TP_ADD_TC(tp, clone5); \
    766 	ATF_TP_ADD_TC_HAVE_PID(tp, clone6); \
    767 	ATF_TP_ADD_TC_HAVE_PID(tp, clone7); \
    768 	ATF_TP_ADD_TC_HAVE_PID(tp, clone8); \
    769 	ATF_TP_ADD_TC(tp, clone_vm1); \
    770 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm2); \
    771 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm3); \
    772 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm4); \
    773 	ATF_TP_ADD_TC(tp, clone_vm5); \
    774 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm6); \
    775 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm7); \
    776 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm8); \
    777 	ATF_TP_ADD_TC(tp, clone_fs1); \
    778 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs2); \
    779 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs3); \
    780 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs4); \
    781 	ATF_TP_ADD_TC(tp, clone_fs5); \
    782 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs6); \
    783 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs7); \
    784 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs8); \
    785 	ATF_TP_ADD_TC(tp, clone_files1); \
    786 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files2); \
    787 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files3); \
    788 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files4); \
    789 	ATF_TP_ADD_TC(tp, clone_files5); \
    790 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files6); \
    791 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files7); \
    792 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files8); \
    793 	ATF_TP_ADD_TC(tp, clone_vfork1); \
    794 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork2); \
    795 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork3); \
    796 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork4); \
    797 	ATF_TP_ADD_TC(tp, clone_vfork5); \
    798 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork6); \
    799 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork7); \
    800 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork8); \
    801 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalignored); \
    802 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_signalmasked); \
    803 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalignored); \
    804 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vm_signalmasked); \
    805 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalignored); \
    806 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_fs_signalmasked); \
    807 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalignored); \
    808 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_files_signalmasked); \
    809 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalignored); \
    810 	ATF_TP_ADD_TC_HAVE_PID(tp, clone_vfork_signalmasked); \
    811 	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone); \
    812 	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vm); \
    813 	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_fs); \
    814 	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_files); \
    815 	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_vfork);
    816 
    817 //	ATF_TP_ADD_TC(tp, clone_sighand1); // XXX
    818 //	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand2); // XXX
    819 //	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand3); // XXX
    820 //	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand4); // XXX
    821 //	ATF_TP_ADD_TC(tp, clone_sighand5); // XXX
    822 //	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand6); // XXX
    823 //	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand7); // XXX
    824 //	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand8); // XXX
    825 
    826 //	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalignored); // XXX
    827 //	ATF_TP_ADD_TC_HAVE_PID(tp, clone_sighand_signalmasked); // XXX
    828 
    829 //	ATF_TP_ADD_TC_HAVE_PID(tp, traceme_vfork_clone_sighand); // XXX
    830