1 /* $NetBSD: t_ptrace_wait.h,v 1.7 2017/01/09 22:09:20 kamil Exp $ */ 2 3 /*- 4 * Copyright (c) 2016 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 17 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 18 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 19 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 20 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* 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 #elif defined(TWAIT_WAITID) 77 # define TWAIT_FNAME "waitid" 78 # define TWAIT_GENERIC(a,b,c) \ 79 waitid(P_PID,(a),NULL,(c)|WEXITED|WTRAPPED) 80 # define TWAIT_WAIT6TYPE(a,b,c,d,e,f) waitid((a),(b),(f),(d)) 81 # define TWAIT_HAVE_PID 1 82 #elif defined(TWAIT_WAIT3) 83 # define TWAIT_FNAME "wait3" 84 # define TWAIT_WAIT4TYPE(a,b,c,d) wait3((b),(c),(d)) 85 # define TWAIT_GENERIC(a,b,c) wait3((b),(c),NULL) 86 # define TWAIT_HAVE_STATUS 1 87 # define TWAIT_HAVE_RUSAGE 1 88 #elif defined(TWAIT_WAIT4) 89 # define TWAIT_FNAME "wait4" 90 # define TWAIT_WAIT4TYPE(a,b,c,d) wait4((a),(b),(c),(d)) 91 # define TWAIT_GENERIC(a,b,c) wait4((a),(b),(c),NULL) 92 # define TWAIT_HAVE_PID 1 93 # define TWAIT_HAVE_STATUS 1 94 # define TWAIT_HAVE_RUSAGE 1 95 #elif defined(TWAIT_WAIT6) 96 # define TWAIT_FNAME "wait6" 97 # define TWAIT_WAIT6TYPE(a,b,c,d,e,f) wait6((a),(b),(c),(d),(e),(f)) 98 # define TWAIT_GENERIC(a,b,c) \ 99 wait6(P_PID,(a),(b),(c)|WEXITED|WTRAPPED,NULL,NULL) 100 # define TWAIT_HAVE_PID 1 101 # define TWAIT_HAVE_STATUS 1 102 #endif 103 104 /* 105 * There are 3 groups of tests: 106 * - TWAIT_GENERIC() (wait, wait2, waitpid, wait3, wait4, wait6) 107 * - TWAIT_WAIT4TYPE() (wait2, waitpid, wait3, wait4) 108 * - TWAIT_WAIT6TYPE() (waitid, wait6) 109 * 110 * Tests only in the above categories are allowed. However some tests are not 111 * possible in the context requested functionality to be verified, therefore 112 * there are helper macros: 113 * - TWAIT_HAVE_PID (wait2, waitpid, waitid, wait4, wait6) 114 * - TWAIT_HAVE_STATUS (wait, wait2, waitpid, wait3, wait4, wait6) 115 * - TWAIT_HAVE_RUSAGE (wait3, wait4) 116 * - TWAIT_HAVE_RETPID (wait, wait2, waitpid, wait3, wait4, wait6) 117 * 118 * If there is an intention to test e.g. wait6(2) specific features in the 119 * ptrace(2) context, find the most matching group and with #ifdefs reduce 120 * functionality of less featured than wait6(2) interface (TWAIT_WAIT6TYPE). 121 * 122 * For clarity never use negative preprocessor checks, like: 123 * #if !defined(TWAIT_WAIT4) 124 * always refer to checks for positive values. 125 */ 126 127 #define TEST_REQUIRE_EQ(x, y) \ 128 do { \ 129 uintmax_t vx = (x); \ 130 uintmax_t vy = (y); \ 131 int ret = vx == vy; \ 132 if (!ret) \ 133 ATF_REQUIRE_EQ_MSG(vx, vy, "%s(%ju) == %s(%ju)", \ 134 #x, vx, #y, vy); \ 135 } while (/*CONSTCOND*/0) 136 137 /* 138 * A child process cannot call atf functions and expect them to magically 139 * work like in the parent. 140 * The printf(3) messaging from a child will not work out of the box as well 141 * without estabilishing a communication protocol with its parent. To not 142 * overcomplicate the tests - do not log from a child and use err(3)/errx(3) 143 * wrapped with FORKEE_ASSERT()/FORKEE_ASSERTX() as that is guaranteed to work. 144 */ 145 #define FORKEE_ASSERT_EQ(x, y) \ 146 do { \ 147 uintmax_t vx = (x); \ 148 uintmax_t vy = (y); \ 149 int ret = vx == vy; \ 150 if (!ret) \ 151 errx(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: " \ 152 "%s(%ju) == %s(%ju)", __FILE__, __LINE__, __func__, \ 153 #x, vx, #y, vy); \ 154 } while (/*CONSTCOND*/0) 155 156 #define FORKEE_ASSERTX(x) \ 157 do { \ 158 int ret = (x); \ 159 if (!ret) \ 160 errx(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: %s",\ 161 __FILE__, __LINE__, __func__, #x); \ 162 } while (/*CONSTCOND*/0) 163 164 #define FORKEE_ASSERT(x) \ 165 do { \ 166 int ret = (x); \ 167 if (!ret) \ 168 err(EXIT_FAILURE, "%s:%d %s(): Assertion failed for: %s",\ 169 __FILE__, __LINE__, __func__, #x); \ 170 } while (/*CONSTCOND*/0) 171 172 /* 173 * Simplify logic for functions using general purpose registers add HAVE_GPREGS 174 * 175 * For platforms that do not implement all needed calls for simplicity assume 176 * that they are unsupported at all. 177 */ 178 #if defined(PT_GETREGS) \ 179 && defined(PT_SETREGS) \ 180 && defined(PTRACE_REG_PC) \ 181 && defined(PTRACE_REG_SET_PC) \ 182 && defined(PTRACE_REG_SP) \ 183 && defined(PTRACE_REG_INTRV) 184 #define HAVE_GPREGS 185 #endif 186 187 /* Add guards for floating point registers */ 188 #if defined(PT_GETFPREGS) \ 189 && defined(PT_SETFPREGS) 190 #define HAVE_FPREGS 191 #endif 192 193 /* Add guards for cpu debug registers */ 194 #if defined(PT_GETDBREGS) \ 195 && defined(PT_SETDBREGS) 196 #define HAVE_DBREGS 197 #endif 198 199 /* 200 * If waitid(2) returns because one or more processes have a state change to 201 * report, 0 is returned. If an error is detected, a value of -1 is returned 202 * and errno is set to indicate the error. If WNOHANG is specified and there 203 * are no stopped, continued or exited children, 0 is returned. 204 */ 205 #if defined(TWAIT_WAITID) 206 #define TWAIT_REQUIRE_SUCCESS(a,b) TEST_REQUIRE_EQ((a), 0) 207 #define TWAIT_REQUIRE_FAILURE(a,b) ATF_REQUIRE_ERRNO((a),(b) == -1) 208 #define FORKEE_REQUIRE_SUCCESS(a,b) FORKEE_ASSERT_EQ(a, 0) 209 #define FORKEE_REQUIRE_FAILURE(a,b) \ 210 FORKEE_ASSERTX(((a) == errno) && ((b) == -1)) 211 #else 212 #define TWAIT_REQUIRE_SUCCESS(a,b) TEST_REQUIRE_EQ((a), (b)) 213 #define TWAIT_REQUIRE_FAILURE(a,b) ATF_REQUIRE_ERRNO((a),(b) == -1) 214 #define FORKEE_REQUIRE_SUCCESS(a,b) FORKEE_ASSERT_EQ(a, b) 215 #define FORKEE_REQUIRE_FAILURE(a,b) \ 216 FORKEE_ASSERTX(((a) == errno) && ((b) == -1)) 217 #endif 218 219 /* 220 * Helper tools to verify whether status reports exited value 221 */ 222 #if TWAIT_HAVE_STATUS 223 static void __used 224 validate_status_exited(int status, int expected) 225 { 226 ATF_REQUIRE_MSG(WIFEXITED(status), "Reported !exited process"); 227 ATF_REQUIRE_MSG(!WIFCONTINUED(status), "Reported continued process"); 228 ATF_REQUIRE_MSG(!WIFSIGNALED(status), "Reported signaled process"); 229 ATF_REQUIRE_MSG(!WIFSTOPPED(status), "Reported stopped process"); 230 231 ATF_REQUIRE_EQ_MSG(WEXITSTATUS(status), expected, 232 "The process has exited with invalid value %d != %d", 233 WEXITSTATUS(status), expected); 234 } 235 236 static void __used 237 forkee_status_exited(int status, int expected) 238 { 239 FORKEE_ASSERTX(WIFEXITED(status)); 240 FORKEE_ASSERTX(!WIFCONTINUED(status)); 241 FORKEE_ASSERTX(!WIFSIGNALED(status)); 242 FORKEE_ASSERTX(!WIFSTOPPED(status)); 243 244 FORKEE_ASSERT_EQ(WEXITSTATUS(status), expected); 245 } 246 247 static void __used 248 validate_status_continued(int status) 249 { 250 ATF_REQUIRE_MSG(!WIFEXITED(status), "Reported exited process"); 251 ATF_REQUIRE_MSG(WIFCONTINUED(status), "Reported !continued process"); 252 ATF_REQUIRE_MSG(!WIFSIGNALED(status), "Reported signaled process"); 253 ATF_REQUIRE_MSG(!WIFSTOPPED(status), "Reported stopped process"); 254 } 255 256 static void __used 257 forkee_status_continued(int status) 258 { 259 FORKEE_ASSERTX(!WIFEXITED(status)); 260 FORKEE_ASSERTX(WIFCONTINUED(status)); 261 FORKEE_ASSERTX(!WIFSIGNALED(status)); 262 FORKEE_ASSERTX(!WIFSTOPPED(status)); 263 } 264 265 static void __used 266 validate_status_signaled(int status, int expected_termsig, int expected_core) 267 { 268 ATF_REQUIRE_MSG(!WIFEXITED(status), "Reported exited process"); 269 ATF_REQUIRE_MSG(!WIFCONTINUED(status), "Reported continued process"); 270 ATF_REQUIRE_MSG(WIFSIGNALED(status), "Reported !signaled process"); 271 ATF_REQUIRE_MSG(!WIFSTOPPED(status), "Reported stopped process"); 272 273 ATF_REQUIRE_EQ_MSG(WTERMSIG(status), expected_termsig, 274 "Unexpected signal received"); 275 276 ATF_REQUIRE_EQ_MSG(WCOREDUMP(status), expected_core, 277 "Unexpectedly core file %s generated", expected_core ? "not" : ""); 278 } 279 280 static void __used 281 forkee_status_signaled(int status, int expected_termsig, int expected_core) 282 { 283 FORKEE_ASSERTX(!WIFEXITED(status)); 284 FORKEE_ASSERTX(!WIFCONTINUED(status)); 285 FORKEE_ASSERTX(WIFSIGNALED(status)); 286 FORKEE_ASSERTX(!WIFSTOPPED(status)); 287 288 FORKEE_ASSERT_EQ(WTERMSIG(status), expected_termsig); 289 FORKEE_ASSERT_EQ(WCOREDUMP(status), expected_core); 290 } 291 292 static void __used 293 validate_status_stopped(int status, int expected) 294 { 295 ATF_REQUIRE_MSG(!WIFEXITED(status), "Reported exited process"); 296 ATF_REQUIRE_MSG(!WIFCONTINUED(status), "Reported continued process"); 297 ATF_REQUIRE_MSG(!WIFSIGNALED(status), "Reported signaled process"); 298 ATF_REQUIRE_MSG(WIFSTOPPED(status), "Reported !stopped process"); 299 300 char st[128], ex[128]; 301 strlcpy(st, strsignal(WSTOPSIG(status)), sizeof(st)); 302 strlcpy(ex, strsignal(expected), sizeof(ex)); 303 304 ATF_REQUIRE_EQ_MSG(WSTOPSIG(status), expected, 305 "Unexpected stop signal received [%s] != [%s]", st, ex); 306 } 307 308 static void __used 309 forkee_status_stopped(int status, int expected) 310 { 311 FORKEE_ASSERTX(!WIFEXITED(status)); 312 FORKEE_ASSERTX(!WIFCONTINUED(status)); 313 FORKEE_ASSERTX(!WIFSIGNALED(status)); 314 FORKEE_ASSERTX(WIFSTOPPED(status)); 315 316 FORKEE_ASSERT_EQ(WSTOPSIG(status), expected); 317 } 318 #else 319 #define validate_status_exited(a,b) 320 #define forkee_status_exited(a,b) 321 #define validate_status_continued(a,b) 322 #define forkee_status_continued(a,b) 323 #define validate_status_signaled(a,b,c) 324 #define forkee_status_signaled(a,b,c) 325 #define validate_status_stopped(a,b) 326 #define forkee_status_stopped(a,b) 327 #endif 328 329 /* This function is currently designed to be run in the main/parent process */ 330 static void __used 331 await_zombie(pid_t process) 332 { 333 struct kinfo_proc2 p; 334 size_t len = sizeof(p); 335 336 const int name[] = { 337 [0] = CTL_KERN, 338 [1] = KERN_PROC2, 339 [2] = KERN_PROC_PID, 340 [3] = process, 341 [4] = sizeof(p), 342 [5] = 1 343 }; 344 345 const size_t namelen = __arraycount(name); 346 347 /* Await the process becoming a zombie */ 348 while(1) { 349 ATF_REQUIRE(sysctl(name, namelen, &p, &len, NULL, 0) == 0); 350 351 if (p.p_stat == LSZOMB) 352 break; 353 354 ATF_REQUIRE(usleep(1000) == 0); 355 } 356 } 357 358 /* Happy number sequence -- this function is used to just consume cpu cycles */ 359 #define HAPPY_NUMBER 1 360 361 /* If n is not happy then its sequence ends in the cycle: 362 * 4, 16, 37, 58, 89, 145, 42, 20, 4, ... */ 363 #define SAD_NUMBER 4 364 365 /* Calculate the sum of the squares of the digits of n */ 366 static unsigned __used 367 dsum(unsigned n) 368 { 369 unsigned sum, x; 370 for (sum = 0; n; n /= 10) { 371 x = n % 10; 372 sum += x * x; 373 } 374 return sum; 375 } 376 377 /* 378 * XXX: Disabled optimization is required to make tests for hardware assisted 379 * traps in .text functional 380 * 381 * Tested with GCC 5.4 on NetBSD 7.99.47 amd64 382 */ 383 static int __used 384 #ifdef __clang__ 385 __attribute__((__optnone__)) 386 #else 387 __attribute__((__optimize__("O0"))) 388 #endif 389 check_happy(unsigned n) 390 { 391 for (;;) { 392 unsigned total = dsum(n); 393 394 if (total == HAPPY_NUMBER) 395 return 1; 396 if (total == SAD_NUMBER) 397 return 0; 398 399 n = total; 400 } 401 } 402 403 #if defined(TWAIT_HAVE_PID) 404 #define ATF_TP_ADD_TC_HAVE_PID(a,b) ATF_TP_ADD_TC(a,b) 405 #else 406 #define ATF_TP_ADD_TC_HAVE_PID(a,b) 407 #endif 408 409 #if defined(HAVE_GPREGS) 410 #define ATF_TP_ADD_TC_HAVE_GPREGS(a,b) ATF_TP_ADD_TC(a,b) 411 #else 412 #define ATF_TP_ADD_TC_HAVE_GPREGS(a,b) 413 #endif 414 415 #if defined(HAVE_FPREGS) 416 #define ATF_TP_ADD_TC_HAVE_FPREGS(a,b) ATF_TP_ADD_TC(a,b) 417 #else 418 #define ATF_TP_ADD_TC_HAVE_FPREGS(a,b) 419 #endif 420 421 #if defined(PT_STEP) 422 #define ATF_TP_ADD_TC_PT_STEP(a,b) ATF_TP_ADD_TC(a,b) 423 #else 424 #define ATF_TP_ADD_TC_PT_STEP(a,b) 425 #endif 426 427 #if defined(__HAVE_PTRACE_WATCHPOINTS) 428 #define ATF_TP_ADD_TC_HAVE_PTRACE_WATCHPOINTS(a,b) ATF_TP_ADD_TC(a,b) 429 #else 430 #define ATF_TP_ADD_TC_HAVE_PTRACE_WATCHPOINTS(a,b) 431 #endif 432