1 /*- 2 * Copyright (c) 2015 John Baldwin <jhb@FreeBSD.org> 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include <sys/types.h> 31 #include <sys/ptrace.h> 32 #include <sys/sysctl.h> 33 #include <sys/user.h> 34 #include <sys/wait.h> 35 #include <errno.h> 36 #include <signal.h> 37 #include <stdlib.h> 38 #include <unistd.h> 39 #include <atf-c.h> 40 41 /* 42 * Verify that a parent debugger process "sees" the exit of a debugged 43 * process exactly once when attached via PT_TRACE_ME. 44 */ 45 ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_trace_me); 46 ATF_TC_BODY(ptrace__parent_wait_after_trace_me, tc) 47 { 48 pid_t child, wpid; 49 int status; 50 51 ATF_REQUIRE((child = fork()) != -1); 52 if (child == 0) { 53 /* Child process. */ 54 ATF_REQUIRE(ptrace(PT_TRACE_ME, 0, NULL, 0) != -1); 55 56 /* Trigger a stop. */ 57 raise(SIGSTOP); 58 59 exit(1); 60 } 61 62 /* Parent process. */ 63 64 /* The first wait() should report the stop from SIGSTOP. */ 65 wpid = waitpid(child, &status, 0); 66 ATF_REQUIRE(wpid == child); 67 ATF_REQUIRE(WIFSTOPPED(status)); 68 ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 69 70 /* Continue the child ignoring the SIGSTOP. */ 71 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1); 72 73 /* The second wait() should report the exit status. */ 74 wpid = waitpid(child, &status, 0); 75 ATF_REQUIRE(wpid == child); 76 ATF_REQUIRE(WIFEXITED(status)); 77 ATF_REQUIRE(WEXITSTATUS(status) == 1); 78 79 /* The child should no longer exist. */ 80 wpid = waitpid(child, &status, 0); 81 ATF_REQUIRE(wpid == -1); 82 ATF_REQUIRE(errno == ECHILD); 83 } 84 85 /* 86 * Verify that a parent debugger process "sees" the exit of a debugged 87 * process exactly once when attached via PT_ATTACH. 88 */ 89 ATF_TC_WITHOUT_HEAD(ptrace__parent_wait_after_attach); 90 ATF_TC_BODY(ptrace__parent_wait_after_attach, tc) 91 { 92 pid_t child, wpid; 93 int cpipe[2], status; 94 char c; 95 96 ATF_REQUIRE(pipe(cpipe) == 0); 97 ATF_REQUIRE((child = fork()) != -1); 98 if (child == 0) { 99 /* Child process. */ 100 close(cpipe[0]); 101 102 /* Wait for the parent to attach. */ 103 ATF_REQUIRE(read(cpipe[1], &c, sizeof(c)) == 0); 104 105 exit(1); 106 } 107 close(cpipe[1]); 108 109 /* Parent process. */ 110 111 /* Attach to the child process. */ 112 ATF_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) == 0); 113 114 /* The first wait() should report the SIGSTOP from PT_ATTACH. */ 115 wpid = waitpid(child, &status, 0); 116 ATF_REQUIRE(wpid == child); 117 ATF_REQUIRE(WIFSTOPPED(status)); 118 ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 119 120 /* Continue the child ignoring the SIGSTOP. */ 121 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1); 122 123 /* Signal the child to exit. */ 124 close(cpipe[0]); 125 126 /* The second wait() should report the exit status. */ 127 wpid = waitpid(child, &status, 0); 128 ATF_REQUIRE(wpid == child); 129 ATF_REQUIRE(WIFEXITED(status)); 130 ATF_REQUIRE(WEXITSTATUS(status) == 1); 131 132 /* The child should no longer exist. */ 133 wpid = waitpid(child, &status, 0); 134 ATF_REQUIRE(wpid == -1); 135 ATF_REQUIRE(errno == ECHILD); 136 } 137 138 /* 139 * Verify that a parent process "sees" the exit of a debugged process only 140 * after the debugger has seen it. 141 */ 142 ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_child_debugger); 143 ATF_TC_BODY(ptrace__parent_sees_exit_after_child_debugger, tc) 144 { 145 pid_t child, debugger, wpid; 146 int cpipe[2], dpipe[2], status; 147 char c; 148 149 ATF_REQUIRE(pipe(cpipe) == 0); 150 ATF_REQUIRE((child = fork()) != -1); 151 152 if (child == 0) { 153 /* Child process. */ 154 close(cpipe[0]); 155 156 /* Wait for parent to be ready. */ 157 ATF_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c)); 158 159 exit(1); 160 } 161 close(cpipe[1]); 162 163 ATF_REQUIRE(pipe(dpipe) == 0); 164 ATF_REQUIRE((debugger = fork()) != -1); 165 166 if (debugger == 0) { 167 /* Debugger process. */ 168 close(dpipe[0]); 169 170 ATF_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1); 171 172 wpid = waitpid(child, &status, 0); 173 ATF_REQUIRE(wpid == child); 174 ATF_REQUIRE(WIFSTOPPED(status)); 175 ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 176 177 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1); 178 179 /* Signal parent that debugger is attached. */ 180 ATF_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c)); 181 182 /* Wait for parent's failed wait. */ 183 ATF_REQUIRE(read(dpipe[1], &c, sizeof(c)) == 0); 184 185 wpid = waitpid(child, &status, 0); 186 ATF_REQUIRE(wpid == child); 187 ATF_REQUIRE(WIFEXITED(status)); 188 ATF_REQUIRE(WEXITSTATUS(status) == 1); 189 190 exit(0); 191 } 192 close(dpipe[1]); 193 194 /* Parent process. */ 195 196 /* Wait for the debugger to attach to the child. */ 197 ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c)); 198 199 /* Release the child. */ 200 ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c)); 201 ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0); 202 close(cpipe[0]); 203 204 /* 205 * Wait for the child to exit. This is kind of gross, but 206 * there is not a better way. 207 */ 208 for (;;) { 209 struct kinfo_proc kp; 210 size_t len; 211 int mib[4]; 212 213 mib[0] = CTL_KERN; 214 mib[1] = KERN_PROC; 215 mib[2] = KERN_PROC_PID; 216 mib[3] = child; 217 len = sizeof(kp); 218 if (sysctl(mib, nitems(mib), &kp, &len, NULL, 0) == -1) { 219 /* The KERN_PROC_PID sysctl fails for zombies. */ 220 ATF_REQUIRE(errno == ESRCH); 221 break; 222 } 223 usleep(5000); 224 } 225 226 /* 227 * This wait should return a pid of 0 to indicate no status to 228 * report. The parent should see the child as non-exited 229 * until the debugger sees the exit. 230 */ 231 wpid = waitpid(child, &status, WNOHANG); 232 ATF_REQUIRE(wpid == 0); 233 234 /* Signal the debugger to wait for the child. */ 235 close(dpipe[0]); 236 237 /* Wait for the debugger. */ 238 wpid = waitpid(debugger, &status, 0); 239 ATF_REQUIRE(wpid == debugger); 240 ATF_REQUIRE(WIFEXITED(status)); 241 ATF_REQUIRE(WEXITSTATUS(status) == 0); 242 243 /* The child process should now be ready. */ 244 wpid = waitpid(child, &status, WNOHANG); 245 ATF_REQUIRE(wpid == child); 246 ATF_REQUIRE(WIFEXITED(status)); 247 ATF_REQUIRE(WEXITSTATUS(status) == 1); 248 } 249 250 /* 251 * Verify that a parent process "sees" the exit of a debugged process 252 * only after a non-direct-child debugger has seen it. In particular, 253 * various wait() calls in the parent must avoid failing with ESRCH by 254 * checking the parent's orphan list for the debugee. 255 */ 256 ATF_TC_WITHOUT_HEAD(ptrace__parent_sees_exit_after_unrelated_debugger); 257 ATF_TC_BODY(ptrace__parent_sees_exit_after_unrelated_debugger, tc) 258 { 259 pid_t child, debugger, fpid, wpid; 260 int cpipe[2], dpipe[2], status; 261 char c; 262 263 ATF_REQUIRE(pipe(cpipe) == 0); 264 ATF_REQUIRE((child = fork()) != -1); 265 266 if (child == 0) { 267 /* Child process. */ 268 close(cpipe[0]); 269 270 /* Wait for parent to be ready. */ 271 ATF_REQUIRE(read(cpipe[1], &c, sizeof(c)) == sizeof(c)); 272 273 exit(1); 274 } 275 close(cpipe[1]); 276 277 ATF_REQUIRE(pipe(dpipe) == 0); 278 ATF_REQUIRE((debugger = fork()) != -1); 279 280 if (debugger == 0) { 281 /* Debugger parent. */ 282 283 /* 284 * Fork again and drop the debugger parent so that the 285 * debugger is not a child of the main parent. 286 */ 287 ATF_REQUIRE((fpid = fork()) != -1); 288 if (fpid != 0) 289 exit(2); 290 291 /* Debugger process. */ 292 close(dpipe[0]); 293 294 ATF_REQUIRE(ptrace(PT_ATTACH, child, NULL, 0) != -1); 295 296 wpid = waitpid(child, &status, 0); 297 ATF_REQUIRE(wpid == child); 298 ATF_REQUIRE(WIFSTOPPED(status)); 299 ATF_REQUIRE(WSTOPSIG(status) == SIGSTOP); 300 301 ATF_REQUIRE(ptrace(PT_CONTINUE, child, (caddr_t)1, 0) != -1); 302 303 /* Signal parent that debugger is attached. */ 304 ATF_REQUIRE(write(dpipe[1], &c, sizeof(c)) == sizeof(c)); 305 306 /* Wait for parent's failed wait. */ 307 ATF_REQUIRE(read(dpipe[1], &c, sizeof(c)) == 0); 308 309 wpid = waitpid(child, &status, 0); 310 ATF_REQUIRE(wpid == child); 311 ATF_REQUIRE(WIFEXITED(status)); 312 ATF_REQUIRE(WEXITSTATUS(status) == 1); 313 314 exit(0); 315 } 316 317 /* Parent process. */ 318 319 /* Wait for the debugger parent process to exit. */ 320 wpid = waitpid(debugger, &status, 0); 321 ATF_REQUIRE(wpid == debugger); 322 ATF_REQUIRE(WIFEXITED(status)); 323 ATF_REQUIRE(WEXITSTATUS(status) == 2); 324 325 /* A WNOHANG wait here should see the non-exited child. */ 326 wpid = waitpid(child, &status, WNOHANG); 327 ATF_REQUIRE(wpid == 0); 328 329 /* Wait for the debugger to attach to the child. */ 330 ATF_REQUIRE(read(dpipe[0], &c, sizeof(c)) == sizeof(c)); 331 332 /* Release the child. */ 333 ATF_REQUIRE(write(cpipe[0], &c, sizeof(c)) == sizeof(c)); 334 ATF_REQUIRE(read(cpipe[0], &c, sizeof(c)) == 0); 335 close(cpipe[0]); 336 337 /* 338 * Wait for the child to exit. This is kind of gross, but 339 * there is not a better way. 340 */ 341 for (;;) { 342 struct kinfo_proc kp; 343 size_t len; 344 int mib[4]; 345 346 mib[0] = CTL_KERN; 347 mib[1] = KERN_PROC; 348 mib[2] = KERN_PROC_PID; 349 mib[3] = child; 350 len = sizeof(kp); 351 if (sysctl(mib, nitems(mib), &kp, &len, NULL, 0) == -1) { 352 /* The KERN_PROC_PID sysctl fails for zombies. */ 353 ATF_REQUIRE(errno == ESRCH); 354 break; 355 } 356 usleep(5000); 357 } 358 359 /* 360 * This wait should return a pid of 0 to indicate no status to 361 * report. The parent should see the child as non-exited 362 * until the debugger sees the exit. 363 */ 364 wpid = waitpid(child, &status, WNOHANG); 365 ATF_REQUIRE(wpid == 0); 366 367 /* Signal the debugger to wait for the child. */ 368 close(dpipe[0]); 369 370 /* Wait for the debugger. */ 371 ATF_REQUIRE(read(dpipe[1], &c, sizeof(c)) == 0); 372 373 /* The child process should now be ready. */ 374 wpid = waitpid(child, &status, WNOHANG); 375 ATF_REQUIRE(wpid == child); 376 ATF_REQUIRE(WIFEXITED(status)); 377 ATF_REQUIRE(WEXITSTATUS(status) == 1); 378 } 379 380 ATF_TP_ADD_TCS(tp) 381 { 382 383 ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_trace_me); 384 ATF_TP_ADD_TC(tp, ptrace__parent_wait_after_attach); 385 ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_child_debugger); 386 ATF_TP_ADD_TC(tp, ptrace__parent_sees_exit_after_unrelated_debugger); 387 388 return (atf_no_error()); 389 } 390