1 /* Copyright (C) 2021 Free Software Foundation, Inc. 2 Contributed by Oracle. 3 4 This file is part of GNU Binutils. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3, or (at your option) 9 any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, 51 Franklin Street - Fifth Floor, Boston, 19 MA 02110-1301, USA. */ 20 21 /* 22 * Lineage events for process fork, exec, etc. 23 */ 24 25 #include "config.h" 26 #include <string.h> 27 #include <elf.h> 28 #include <regex.h> 29 #include <sys/types.h> 30 #include <sys/stat.h> 31 #include <sys/mman.h> 32 33 #include "descendants.h" 34 35 /* TprintfT(<level>,...) definitions. Adjust per module as needed */ 36 #define DBG_LT0 0 // for high-level configuration, unexpected errors/warnings 37 #define DBG_LTT 0 // for interposition on GLIBC functions 38 #define DBG_LT1 1 // for configuration details, warnings 39 #define DBG_LT2 2 40 #define DBG_LT3 3 41 42 #define LT_MAXNAMELEN 1024 43 #define LT_MAXPATHLEN 1024 44 45 int __collector_linetrace_shutdown_hwcs_6830763_XXXX = 0; 46 int dbg_current_mode = FOLLOW_NONE; /* for debug only */ 47 unsigned line_key = COLLECTOR_TSD_INVALID_KEY; 48 line_mode_t line_mode = LM_DORMANT; 49 int user_follow_mode = FOLLOW_ON; 50 int java_mode = 0; 51 52 static char *user_follow_spec; 53 static char new_lineage[LT_MAXNAMELEN]; 54 static char curr_lineage[LT_MAXNAMELEN]; 55 static char linetrace_exp_dir_name[LT_MAXPATHLEN + 1]; // experiment directory 56 57 /* lineage tracking for descendants of this process */ 58 59 static int fork_linenum = 0; 60 static int line_initted = 0; 61 static collector_mutex_t fork_lineage_lock = COLLECTOR_MUTEX_INITIALIZER; 62 static collector_mutex_t clone_lineage_lock = COLLECTOR_MUTEX_INITIALIZER; 63 64 /* interposition */ 65 #define CALL_REAL(x) (*(int(*)())__real_##x) 66 #define CALL_REALC(x) (*(char*(*)())__real_##x) 67 #define CALL_REALF(x) (*(FILE*(*)())__real_##x) 68 #define NULL_PTR(x) ( __real_##x == NULL ) 69 70 // For a given Linux, which lib functions have more than one GLIBC version? Do this: 71 // objdump -T `find /lib /lib64 -name "*.so*"` | grep GLIBC | grep text | grep \( 72 static void *__real_fork = NULL; 73 static void *__real_vfork = NULL; 74 static void *__real_execve = NULL; 75 static void *__real_execvp = NULL; 76 static void *__real_execv = NULL; 77 static void *__real_execle = NULL; 78 static void *__real_execlp = NULL; 79 static void *__real_execl = NULL; 80 static void *__real_clone = NULL; 81 static void *__real_grantpt = NULL; 82 static void *__real_ptsname = NULL; 83 static void *__real_popen = NULL; 84 static int clone_linenum = 0; 85 #if ARCH(Intel) 86 #if WSIZE(32) 87 static void *__real_popen_2_1 = NULL; 88 static void *__real_popen_2_0 = NULL; 89 static void *__real_posix_spawn_2_15 = NULL; 90 static void *__real_posix_spawnp_2_15 = NULL; 91 static void *__real_posix_spawn_2_2 = NULL; 92 static void *__real_posix_spawnp_2_2 = NULL; 93 #elif WSIZE(64) 94 static void *__real_posix_spawn_2_15 = NULL; 95 static void *__real_posix_spawnp_2_15 = NULL; 96 static void *__real_posix_spawn_2_2_5 = NULL; 97 static void *__real_posix_spawnp_2_2_5 = NULL; 98 #endif /* WSIZE() */ 99 #endif /* ARCH(Intel) */ 100 static void *__real_system = NULL; 101 static void *__real_posix_spawn = NULL; 102 static void *__real_posix_spawnp = NULL; 103 static void *__real_setuid = NULL; 104 static void *__real_seteuid = NULL; 105 static void *__real_setreuid = NULL; 106 static void *__real_setgid = NULL; 107 static void *__real_setegid = NULL; 108 static void *__real_setregid = NULL; 109 static void linetrace_dormant (); 110 static int check_follow_fork (); 111 static int check_follow_exec (const char *execfile); 112 static int check_follow_combo (const char *execfile); 113 static int path_collectable (const char *execfile); 114 static char * build_experiment_path (char *instring, size_t instring_sz, const char *lineage_str); 115 static int init_lineage_intf (); 116 117 /* ------- "Previously dbx-visible" function prototypes ----------------- */ 118 static int linetrace_follow_experiment (const char *follow_spec, const char *lineage_str, const char *execfile); 119 static char *lineage_from_expname (char *lineage_str, size_t lstr_sz, const char *expname); 120 static void linetrace_ext_fork_prologue (const char *variant, char * new_lineage, int *following_fork); 121 static void linetrace_ext_fork_epilogue (const char *variant, const pid_t ret, char * new_lineage, int *following_fork); 122 static char **linetrace_ext_exec_prologue (const char *variant, 123 const char* path, char *const argv[], char *const envp[], int *following_exec); 124 static void linetrace_ext_exec_epilogue (const char *variant, char *const envp[], const int ret, int *following_exec); 125 static void linetrace_ext_combo_prologue (const char *variant, const char *cmd, int *following_combo); 126 static void linetrace_ext_combo_epilogue (const char *variant, const int ret, int *following_combo); 127 128 #ifdef DEBUG 129 static int 130 get_combo_flag () 131 { 132 int * guard = NULL; 133 int combo_flag = ((line_mode == LM_TRACK_LINEAGE) ? ((CHCK_REENTRANCE (guard)) ? 1 : 0) : 0); 134 return combo_flag; 135 } 136 #endif /* DEBUG */ 137 138 /* must be called for potentially live experiment */ 139 int 140 __collector_ext_line_init (int *precord_this_experiment, 141 const char * progspec, const char * progname) 142 { 143 *precord_this_experiment = 1; 144 TprintfT (DBG_LT0, "__collector_ext_line_init(%s)\n", progspec); 145 if (NULL_PTR (fork)) 146 if (init_lineage_intf ()) 147 { 148 TprintfT (DBG_LT0, "__collector_ext_line_init() ERROR: initialization failed.\n"); 149 return COL_ERROR_LINEINIT; 150 } 151 /* check the follow spec */ 152 user_follow_spec = CALL_UTIL (getenv)(SP_COLLECTOR_FOLLOW_SPEC); 153 if (user_follow_spec != NULL) 154 { 155 TprintfT (DBG_LT0, "collector: %s=%s\n", SP_COLLECTOR_FOLLOW_SPEC, user_follow_spec); 156 if (!linetrace_follow_experiment (user_follow_spec, curr_lineage, progname)) 157 { 158 *precord_this_experiment = 0; 159 TprintfT (DBG_LT0, "collector: -F =<regex> does not match, will NOT be followed\n"); 160 } 161 else 162 TprintfT (DBG_LT0, "collector: -F =<regex> matches, will be followed\n"); 163 user_follow_mode = FOLLOW_ALL; 164 } 165 __collector_env_save_preloads (); 166 TprintfT (DBG_LT0, "__collector_ext_line_init(), progname=%s, followspec=%s, followthis=%d\n", 167 progname, user_follow_spec ? user_follow_spec : "NULL", 168 *precord_this_experiment); 169 line_mode = LM_TRACK_LINEAGE; /* even if we don't follow, we report the interposition */ 170 line_initted = 1; 171 return COL_ERROR_NONE; 172 } 173 174 /* 175 * int __collector_ext_line_install(args) 176 * Check args to determine which line events to follow. 177 * Create tsd key for combo flag. 178 */ 179 int 180 __collector_ext_line_install (char *args, const char * expname) 181 { 182 if (!line_initted) 183 { 184 TprintfT (DBG_LT0, "__collector_ext_line_install(%s) ERROR: init hasn't be called yet\n", args); 185 return COL_ERROR_EXPOPEN; 186 } 187 TprintfT (DBG_LT0, "__collector_ext_line_install(%s, %s)\n", args, expname); 188 line_key = __collector_tsd_create_key (sizeof (int), NULL, NULL); 189 190 /* determine experiment name */ 191 __collector_strlcpy (linetrace_exp_dir_name, expname, sizeof (linetrace_exp_dir_name)); 192 lineage_from_expname (curr_lineage, sizeof (curr_lineage), linetrace_exp_dir_name); 193 user_follow_mode = CALL_UTIL (atoi)(args); 194 TprintfT (DBG_LT0, "__collector_ext_line_install() user_follow_mode=0x%X, linetrace_exp_dir_name=%s\n", 195 user_follow_mode, linetrace_exp_dir_name); 196 197 // determine java mode 198 char * java_follow_env = CALL_UTIL (getenv)(JAVA_TOOL_OPTIONS); 199 if (java_follow_env != NULL && CALL_UTIL (strstr)(java_follow_env, COLLECTOR_JVMTI_OPTION)) 200 java_mode = 1; 201 202 // backup collector specific env 203 if (sp_env_backup == NULL) 204 { 205 sp_env_backup = __collector_env_backup (); 206 TprintfT (DBG_LT0, "__collector_ext_line_install creating sp_env_backup -- 0x%p\n", sp_env_backup); 207 } 208 else 209 TprintfT (DBG_LT0, "__collector_ext_line_install existing sp_env_backup -- 0x%p\n", sp_env_backup); 210 if (user_follow_mode == FOLLOW_NONE) 211 __collector_env_unset (NULL); 212 213 char logmsg[256]; 214 logmsg[0] = '\0'; 215 if (user_follow_mode != FOLLOW_NONE) 216 CALL_UTIL (strlcat)(logmsg, "fork|exec|combo", sizeof (logmsg)); 217 size_t slen = __collector_strlen (logmsg); 218 if (slen > 0) 219 logmsg[slen] = '\0'; 220 else 221 CALL_UTIL (strlcat)(logmsg, "none", sizeof (logmsg)); 222 223 /* report which line events are followed */ 224 (void) __collector_log_write ("<setting %s=\"%s\"/>\n", SP_JCMD_LINETRACE, logmsg); 225 TprintfT (DBG_LT0, "__collector_ext_line_install(%s): %s \n", expname, logmsg); 226 return COL_ERROR_NONE; 227 } 228 229 char * 230 lineage_from_expname (char *lineage_str, size_t lstr_sz, const char *expname) 231 { 232 TprintfT (DBG_LT0, "lineage_from_expname(%s, %s)\n", lineage_str, expname); 233 char *p = NULL; 234 if (lstr_sz < 1 || !lineage_str || !expname) 235 { 236 TprintfT (DBG_LT0, "lineage_from_expname(): ERROR, null string\n"); 237 return NULL; 238 } 239 /* determine lineage from experiment name */ 240 p = __collector_strrchr (expname, '/'); 241 if ((p == NULL) || (*++p != '_')) 242 { 243 lineage_str[0] = 0; 244 TprintfT (DBG_LT2, "lineage_from_expname(): expt=%s lineage=\".\" (founder)\n", expname); 245 } 246 else 247 { 248 size_t tmp = __collector_strlcpy (lineage_str, p, lstr_sz); 249 if (tmp >= lstr_sz) 250 TprintfT (DBG_LT0, "lineage_from_expname(): ERROR: expt=%s lineage=\"%s\" truncated %ld characters\n", 251 expname, lineage_str, (long) (tmp - lstr_sz)); 252 lineage_str[lstr_sz - 1] = 0; 253 p = __collector_strchr (lineage_str, '.'); 254 if (p != NULL) 255 *p = '\0'; 256 TprintfT (DBG_LT2, "lineage_from_expname(): expt=%s lineage=\"%s\"\n", expname, lineage_str); 257 } 258 return lineage_str; 259 } 260 261 /* 262 * void __collector_line_cleanup (void) 263 * Disable logging. Clear backup ENV. 264 */ 265 void 266 __collector_line_cleanup (void) 267 { 268 if (line_mode == LM_CLOSED) 269 { 270 TprintfT (DBG_LT0, "__collector_line_cleanup(): WARNING, line is already closed\n"); 271 return; 272 } 273 else if (line_mode == LM_DORMANT) 274 TprintfT (DBG_LT0, "__collector_line_cleanup(): ERROR, line is DORMANT\n"); 275 else 276 TprintfT (DBG_LT0, "__collector_line_cleanup()\n"); 277 line_mode = LM_CLOSED; 278 user_follow_mode = FOLLOW_NONE; 279 dbg_current_mode = FOLLOW_NONE; /* for debug only */ 280 line_key = COLLECTOR_TSD_INVALID_KEY; 281 java_mode = 0; 282 if (sp_env_backup != NULL) 283 { 284 __collector_env_backup_free (); 285 sp_env_backup = NULL; 286 } 287 return; 288 } 289 290 /* 291 * void __collector_ext_line_close (void) 292 * Disable logging. Cleans ENV vars. Clear backup ENV. 293 */ 294 void 295 __collector_ext_line_close (void) 296 { 297 TprintfT (DBG_LT0, "__collector_ext_line_close()\n"); 298 __collector_line_cleanup (); 299 __collector_env_unset (NULL); 300 return; 301 } 302 303 /* 304 * void linetrace_dormant(void) 305 * Disable logging. Preserve ENV vars. 306 */ 307 static void 308 linetrace_dormant (void) 309 { 310 if (line_mode == LM_DORMANT) 311 { 312 TprintfT (DBG_LT0, "linetrace_dormant() -- already dormant\n"); 313 return; 314 } 315 else if (line_mode == LM_CLOSED) 316 { 317 TprintfT (DBG_LT0, "linetrace_dormant(): ERROR, line is already CLOSED\n"); 318 return; 319 } 320 else 321 TprintfT (DBG_LT0, "linetrace_dormant()\n"); 322 line_mode = LM_DORMANT; 323 return; 324 } 325 326 static int 327 check_follow_fork () 328 { 329 int follow = (user_follow_mode != FOLLOW_NONE); 330 TprintfT (DBG_LT0, "check_follow_fork()=%d\n", follow); 331 return follow; 332 } 333 334 static int 335 check_follow_exec (const char *execfile) 336 { 337 int follow = (user_follow_mode != FOLLOW_NONE); 338 if (follow) 339 { 340 /* revise based on collectability of execfile */ 341 follow = path_collectable (execfile); 342 } 343 TprintfT (DBG_LT0, "check_follow_exec(%s)=%d\n", execfile, follow); 344 return follow; 345 } 346 347 static int 348 check_follow_combo (const char *execfile) 349 { 350 int follow = (user_follow_mode != FOLLOW_NONE); 351 TprintfT (DBG_LT0, "check_follow_combo(%s)=%d\n", execfile, follow); 352 return follow; 353 } 354 355 static int 356 check_fd_dynamic (int fd) 357 { 358 TprintfT (DBG_LT0, "check_fd_dynamic(%d)\n", fd); 359 off_t off = CALL_UTIL (lseek)(fd, (off_t) 0, SEEK_END); 360 size_t sz = (size_t) 8192; /* one page should suffice */ 361 if (sz > off) 362 sz = off; 363 char *p = CALL_UTIL (mmap64)((char *) 0, sz, PROT_READ, MAP_PRIVATE, fd, (off64_t) 0); 364 if (p == MAP_FAILED) 365 { 366 TprintfT (DBG_LT0, "check_fd_dynamic(): ERROR/WARNING: mmap failed for `%d'\n", fd); 367 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%s</event>\n", SP_JCMD_CWARN, 368 COL_WARN_NOFOLLOW, "mmap-failed"); 369 return 0; 370 } 371 char elfclass = p[EI_CLASS]; 372 if ((p[EI_MAG0] != ELFMAG0) || 373 (p[EI_MAG1] != ELFMAG1) || 374 (p[EI_MAG2] != ELFMAG2) || 375 (p[EI_MAG3] != ELFMAG3) || 376 (elfclass != ELFCLASS32 && elfclass != ELFCLASS64) 377 ) 378 { 379 TprintfT (DBG_LT0, "check_fd_dynamic(): WARNING: Command `%d' is not executable ELF!\n", fd); 380 CALL_UTIL (munmap)(p, sz); 381 return 1; 382 } 383 Elf32_Ehdr *ehdr32 = (Elf32_Ehdr*) p; 384 Elf64_Ehdr *ehdr64 = (Elf64_Ehdr*) p; 385 Elf64_Off e_phoff; 386 Elf64_Half e_phnum; 387 Elf64_Half e_phentsize; 388 if (elfclass == ELFCLASS32) 389 { 390 e_phoff = ehdr32->e_phoff; 391 e_phnum = ehdr32->e_phnum; 392 e_phentsize = ehdr32->e_phentsize; 393 } 394 else 395 { 396 e_phoff = ehdr64->e_phoff; 397 e_phnum = ehdr64->e_phnum; 398 e_phentsize = ehdr64->e_phentsize; 399 } 400 if ((sizeof (Elf32_Ehdr) > sz) || 401 (sizeof (Elf64_Ehdr) > sz) || 402 (e_phoff + e_phentsize * (e_phnum - 1) > sz)) 403 { 404 TprintfT (DBG_LT0, "check_fd_dynamic(): WARNING: Command `%d' ELF file did not fit in page!\n", fd); 405 #if 0 406 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%s</event>\n", SP_JCMD_CWARN, 407 COL_WARN_RISKYFOLLOW, "ELF header size"); 408 #endif 409 CALL_UTIL (munmap)(p, sz); 410 return 1; 411 } 412 TprintfT (DBG_LT2, "check_fd_dynamic(): elfclass=%d, e_phoff=%lu e_phnum=%lu e_phentsize=%lu\n", 413 (int) elfclass, (unsigned long) e_phoff, (unsigned long) e_phnum, 414 (unsigned long) e_phentsize); 415 int dynamic = 0; 416 Elf64_Half i; 417 for (i = 0; i < e_phnum; i++) 418 { 419 if (elfclass == ELFCLASS32) 420 { 421 if (PT_DYNAMIC == 422 ((Elf32_Phdr*) (p + e_phoff + e_phentsize * i))->p_type) 423 { 424 dynamic = 1; 425 break; 426 } 427 } 428 else 429 { 430 if (PT_DYNAMIC == 431 ((Elf64_Phdr*) (p + e_phoff + e_phentsize * i))->p_type) 432 { 433 dynamic = 1; 434 break; 435 } 436 } 437 } 438 if (!dynamic) 439 { 440 TprintfT (DBG_LT0, "check_fd_dynamic(): ERROR/WARNING: Command `%d' is not a dynamic executable!\n", fd); 441 #if 0 442 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%s</event>\n", SP_JCMD_CWARN, 443 COL_WARN_NOFOLLOW, "!dynamic"); 444 #endif 445 } 446 else 447 TprintfT (DBG_LT2, "check_fd_dynamic(): Command `%d' is a dynamic executable!\n", fd); 448 CALL_UTIL (munmap)(p, sz); 449 return dynamic; 450 } 451 452 static int 453 check_dynamic (const char *execfile) 454 { 455 TprintfT (DBG_LT2, "check_dynamic(%s)\n", execfile); 456 int fd = CALL_UTIL (open)(execfile, O_RDONLY); 457 if (fd == -1) 458 { 459 TprintfT (DBG_LT0, "check_dynamic(): ERROR/WARNING: Command `%s' could not be opened!\n", execfile); 460 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%s</event>\n", SP_JCMD_CWARN, 461 COL_WARN_RISKYFOLLOW, "open"); 462 return 1; /* follow, though exec will presumably fail */ 463 } 464 int ret = check_fd_dynamic (fd); 465 CALL_UTIL (close)(fd); 466 return ret; 467 } 468 469 static int 470 path_collectable (const char *execfile) 471 { 472 TprintfT (DBG_LT0, "path_collectable(%s)\n", execfile); 473 /* Check that execfile exists and is a collectable executable */ 474 /* logging warning when collection is likely to be unsuccessful */ 475 /* (if check isn't accurate, generally best not to include it) */ 476 477 if (execfile && !__collector_strchr (execfile, '/')) 478 { /* got an unqualified name */ 479 /* XXXX locate execfile on PATH to be able to check it */ 480 TprintfT (DBG_LT0, "path_collectable(): WARNING: Can't check unqualified executable `%s'\n", execfile); 481 #if 0 482 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%s</event>\n", SP_JCMD_CWARN, 483 COL_WARN_RISKYFOLLOW, "path"); 484 #endif 485 return 1; /* follow unqualified execfile unchecked */ 486 } 487 struct stat sbuf; 488 if (stat (execfile, &sbuf)) 489 { /* can't stat it */ 490 TprintfT (DBG_LT0, "path_collectable(): WARNING: Can't stat `%s'\n", execfile); 491 #if 0 492 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%s</event>\n", SP_JCMD_CWARN, 493 COL_WARN_RISKYFOLLOW, "stat"); 494 #endif 495 return 1; /* follow, though exec will probably fail */ 496 } 497 TprintfT (DBG_LT2, "path_collectable(%s) mode=0%o uid=%d gid=%d\n", 498 execfile, sbuf.st_mode, sbuf.st_uid, sbuf.st_gid); 499 if (((sbuf.st_mode & S_IXUSR) == 0) || ((sbuf.st_mode & S_IFMT) == S_IFDIR)) 500 { 501 TprintfT (DBG_LT0, "path_collectable(): WARNING: Command `%s' is NOT an executable file!\n", execfile); 502 #if 0 503 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%s</event>\n", SP_JCMD_CWARN, 504 COL_WARN_RISKYFOLLOW, "mode"); 505 #endif 506 return 1; /* follow, though exec will presumably fail */ 507 } 508 /* XXXX setxid(root) is OK iff libcollector is registered as secure */ 509 /* XXXX setxid(non-root) is OK iff umask is accomodating */ 510 if (((sbuf.st_mode & S_ISUID) != 0) || ((sbuf.st_mode & S_ISGID) != 0)) 511 { 512 TprintfT (DBG_LT0, "path_collectable(): WARNING: Command `%s' is SetXID!\n", execfile); 513 #if 0 514 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%s</event>\n", SP_JCMD_CWARN, 515 COL_WARN_RISKYFOLLOW, "setxid"); 516 #endif 517 return 1; /* follow, though collection may be unreliable */ 518 } 519 if (!check_dynamic (execfile)) 520 { 521 TprintfT (DBG_LT0, "path_collectable(%s) WARNING/ERROR: not dynamic, not collectng!\n", execfile); 522 return 0; /* don't follow, collection will fail unpredictably */ 523 } 524 TprintfT (DBG_LT2, "path_collectable(%s) OK!\n", execfile); 525 return 1; /* OK to follow */ 526 } 527 528 static char * 529 build_experiment_path (char * instring, size_t instring_sz, const char *lineage_str) 530 { 531 TprintfT (DBG_LT0, "build_experiment_path(,%ld, %s)\n", 532 (long) instring_sz, lineage_str); 533 const char *p = CALL_UTIL (strstr)(linetrace_exp_dir_name, DESCENDANT_EXPT_KEY); 534 int basedir_sz; 535 if (p) 536 basedir_sz = p - linetrace_exp_dir_name + 4; /* +3 because of DESCENDANT_EXPT_KEY */ 537 else 538 basedir_sz = __collector_strlen (linetrace_exp_dir_name) + 1; 539 int additional_sz = __collector_strlen (lineage_str) + 4; 540 if (basedir_sz + additional_sz > instring_sz) 541 { 542 TprintfT (DBG_LT0, "build_experiment_path(%s,%s): ERROR: path too long: %d > %ld\n", 543 linetrace_exp_dir_name, lineage_str, 544 basedir_sz + additional_sz, (long) instring_sz); 545 *instring = 0; 546 return NULL; 547 } 548 __collector_strlcpy (instring, linetrace_exp_dir_name, basedir_sz); 549 size_t slen = __collector_strlen (instring); 550 CALL_UTIL (snprintf)(instring + slen, instring_sz - slen, "/%s.er", lineage_str); 551 assert (__collector_strlen (instring) + 1 == basedir_sz + additional_sz); 552 return instring; 553 } 554 555 static void 556 check_reuid_change (uid_t ruid, uid_t euid) 557 { 558 uid_t curr_ruid = getuid (); 559 uid_t curr_euid = geteuid (); 560 mode_t curr_umask = umask (0); 561 umask (curr_umask); /* restore original umask */ 562 int W_oth = !(curr_umask & S_IWOTH); 563 TprintfT (DBG_LT0, "check_reuid_change(%d,%d): umask=%03o\n", ruid, euid, curr_umask); 564 TprintfT (DBG_LT0, "check_reuid_change(): umask W usr=%d grp=%d oth=%d\n", 565 (int) (!(curr_umask & S_IWUSR)), (int) (!(curr_umask & S_IWGRP)), W_oth); 566 if (ruid != -1) 567 { 568 TprintfT (DBG_LT0, "check_reuid_change(%d->%d)\n", curr_ruid, ruid); 569 if ((curr_euid == 0) && (ruid != 0) && !W_oth) 570 { 571 /* changing to non-root ID, with umask blocking writes by other */ 572 TprintfT (DBG_LT0, "check_reuid_change(): ERROR/WARNING: umask blocks write other after ruid change (%d->%d)\n", 573 curr_ruid, ruid); 574 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">umask %03o ruid %d->%d</event>\n", 575 SP_JCMD_CWARN, COL_WARN_IDCHNG, curr_umask, curr_ruid, ruid); 576 } 577 } 578 if (euid != -1) 579 { 580 TprintfT (DBG_LT0, "check_reuid_change(%d->%d)\n", curr_euid, euid); 581 if ((curr_euid == 0) && (euid != 0) && !W_oth) 582 { 583 /* changing to non-root ID, with umask blocking writes by other */ 584 TprintfT (DBG_LT0, "check_reuid_change(): ERROR/WARNING: umask blocks write other after euid change (%d->%d)\n", 585 curr_euid, euid); 586 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">umask %03o euid %d->%d</event>\n", 587 SP_JCMD_CWARN, COL_WARN_IDCHNG, curr_umask, curr_euid, euid); 588 } 589 } 590 } 591 592 static void 593 check_regid_change (gid_t rgid, gid_t egid) 594 { 595 gid_t curr_rgid = getgid (); 596 gid_t curr_egid = getegid (); 597 uid_t curr_euid = geteuid (); 598 mode_t curr_umask = umask (0); 599 umask (curr_umask); /* restore original umask */ 600 int W_oth = !(curr_umask & S_IWOTH); 601 TprintfT (DBG_LT0, "check_regid_change(%d,%d): umask=%03o euid=%d\n", 602 rgid, egid, curr_umask, curr_euid); 603 TprintfT (DBG_LT0, "umask W usr=%d grp=%d oth=%d\n", 604 (int) (!(curr_umask & S_IWUSR)), (int) (!(curr_umask & S_IWGRP)), W_oth); 605 if (rgid != -1) 606 { 607 TprintfT (DBG_LT0, "check_regid_change(%d->%d)\n", curr_rgid, rgid); 608 if ((curr_euid == 0) && (rgid != 0) && !W_oth) 609 { 610 /* changing to non-root ID, with umask blocking writes by other */ 611 TprintfT (DBG_LT0, "check_regid_change(): WARNING/ERROR: umask blocks write other after rgid change (%d->%d)\n", 612 curr_rgid, rgid); 613 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">umask %03o rgid %d->%d</event>\n", 614 SP_JCMD_CWARN, COL_WARN_IDCHNG, curr_umask, curr_rgid, rgid); 615 } 616 } 617 if (egid != -1) 618 { 619 TprintfT (DBG_LT0, "check_regid_change(): check_egid_change(%d->%d)\n", curr_egid, egid); 620 if ((curr_euid == 0) && (egid != 0) && !W_oth) 621 { 622 /* changing to non-root ID, with umask blocking writes by other */ 623 TprintfT (DBG_LT0, "check_regid_change(): WARNING/ERROR: umask blocks write other after egid change (%d->%d)\n", 624 curr_egid, egid); 625 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">umask %03o egid %d->%d</event>\n", 626 SP_JCMD_CWARN, COL_WARN_IDCHNG, curr_umask, curr_egid, egid); 627 } 628 } 629 } 630 631 static int 632 init_lineage_intf () 633 { 634 void *dlflag; 635 TprintfT (DBG_LT2, "init_lineage_intf()\n"); 636 637 static int nesting_check = 0; 638 if (nesting_check >= 2) 639 { 640 /* segv before stack blows up */ 641 nesting_check /= (nesting_check - 2); 642 } 643 nesting_check++; 644 645 __real_fork = dlsym (RTLD_NEXT, "fork"); 646 if (__real_fork == NULL) 647 { 648 __real_fork = dlsym (RTLD_DEFAULT, "fork"); 649 if (__real_fork == NULL) 650 return 1; 651 dlflag = RTLD_DEFAULT; 652 } 653 else 654 dlflag = RTLD_NEXT; 655 TprintfT (DBG_LT2, "init_lineage_intf() using RTLD_%s\n", 656 dlflag == RTLD_DEFAULT ? "DEFAULT" : "NEXT"); 657 TprintfT (DBG_LT2, "init_lineage_intf() @0x%p __real_fork\n", __real_fork); 658 __real_vfork = dlsym (dlflag, "vfork"); 659 TprintfT (DBG_LT2, "init_lineage_intf() @0x%p __real_vfork\n", __real_vfork); 660 __real_execve = dlsym (dlflag, "execve"); 661 TprintfT (DBG_LT2, "init_lineage_intf() @0x%p __real_execve\n", __real_execve); 662 __real_execvp = dlsym (dlflag, "execvp"); 663 TprintfT (DBG_LT2, "init_lineage_intf() @0x%p __real_execvp\n", __real_execvp); 664 __real_execv = dlsym (dlflag, "execv"); 665 TprintfT (DBG_LT2, "init_lineage_intf() @0x%p __real_execv\n", __real_execv); 666 __real_execle = dlsym (dlflag, "execle"); 667 TprintfT (DBG_LT2, "init_lineage_intf() @0x%p __real_execle\n", __real_execle); 668 __real_execlp = dlsym (dlflag, "execlp"); 669 TprintfT (DBG_LT2, "init_lineage_intf() @0x%p __real_execlp\n", __real_execlp); 670 __real_execl = dlsym (dlflag, "execl"); 671 TprintfT (DBG_LT2, "init_lineage_intf() @0x%p __real_execl\n", __real_execl); 672 __real_clone = dlsym (dlflag, "clone"); 673 TprintfT (DBG_LT2, "init_lineage_intf() @0x%p __real_clone\n", __real_clone); 674 __real_posix_spawn = dlsym (dlflag, "posix_spawn"); 675 TprintfT (DBG_LT2, "init_lineage_intf() @0x%p __real_posix_spawn\n", 676 __real_posix_spawn); 677 __real_posix_spawnp = dlsym (dlflag, "posix_spawnp"); 678 TprintfT (DBG_LT2, "init_lineage_intf() @0x%p __real_posix_spawnp\n", 679 __real_posix_spawnp); 680 __real_popen = dlvsym (dlflag, "popen", SYS_POPEN_VERSION); 681 TprintfT (DBG_LT2, "init_lineage_intf()[%s] @0x%p __real_popen\n", 682 SYS_POPEN_VERSION, __real_popen); 683 #if ARCH(Intel) 684 __real_posix_spawn_2_15 = dlvsym (dlflag, "posix_spawn", SYS_POSIX_SPAWN_VERSION); 685 __real_posix_spawnp_2_15 = dlvsym (dlflag, "posix_spawnp", SYS_POSIX_SPAWN_VERSION); 686 #if WSIZE(32) 687 __real_popen_2_1 = __real_popen; 688 __real_popen_2_0 = dlvsym (dlflag, "popen", "GLIBC_2.0"); 689 __real_posix_spawn_2_2 = dlvsym (dlflag, "posix_spawn", "GLIBC_2.2"); 690 __real_posix_spawnp_2_2 = dlvsym (dlflag, "posix_spawnp", "GLIBC_2.2"); 691 #elif WSIZE(64) 692 __real_posix_spawn_2_2_5 = dlvsym (dlflag, "posix_spawn", "GLIBC_2.2.5"); 693 __real_posix_spawnp_2_2_5 = dlvsym (dlflag, "posix_spawnp", "GLIBC_2.2.5"); 694 #endif /* WSIZE() */ 695 #endif /* ARCH(Intel) */ 696 __real_grantpt = dlsym (dlflag, "grantpt"); 697 TprintfT (DBG_LT2, "init_lineage_intf() @0x%p __real_grantpt\n", __real_grantpt); 698 __real_ptsname = dlsym (dlflag, "ptsname"); 699 TprintfT (DBG_LT2, "init_lineage_intf() @0x%p __real_ptsname\n", __real_ptsname); 700 __real_system = dlsym (dlflag, "system"); 701 TprintfT (DBG_LT2, "init_lineage_intf() @0x%p __real_system\n", __real_system); 702 __real_setuid = dlsym (dlflag, "setuid"); 703 TprintfT (DBG_LT2, "init_lineage_intf() @0x%p __real_setuid\n", __real_setuid); 704 __real_seteuid = dlsym (dlflag, "seteuid"); 705 TprintfT (DBG_LT2, "init_lineage_intf() @0x%p __real_seteuid\n", __real_seteuid); 706 __real_setreuid = dlsym (dlflag, "setreuid"); 707 TprintfT (DBG_LT2, "init_lineage_intf() @0x%p __real_setreuid\n", __real_setreuid); 708 __real_setgid = dlsym (dlflag, "setgid"); 709 TprintfT (DBG_LT2, "init_lineage_intf() @0x%p __real_setgid\n", __real_setgid); 710 __real_setegid = dlsym (dlflag, "setegid"); 711 TprintfT (DBG_LT2, "init_lineage_intf() @0x%p __real_setegid\n", __real_setegid); 712 __real_setregid = dlsym (dlflag, "setregid"); 713 TprintfT (DBG_LT2, "init_lineage_intf() @0x%p __real_setregid\n", __real_setregid); 714 return 0; 715 } 716 717 /*------------------------------------------------------------------------ */ 718 /* Note: The following _prologue and _epilogue functions used to be dbx-visible. 719 720 They are used to appropriately manage lineage-changing events, by 721 quiescing and re-enabling/re-setting experiment collection before and after, 722 and logging the lineage-change in the process/experiment undertaking it. 723 As shown by the interposition functions for fork, exec, etc., which follow, 724 the _prologue should be called immediately prior (such as a breakpoint 725 action defined at function entry) and the _epilogue called immediately 726 after (such as a breakpoint action defined at function return). 727 */ 728 729 /* 730 Notes on MT from Solaris 10 man pthread_atfork: 731 732 All multithreaded applications that call fork() in a POSIX 733 threads program and do more than simply call exec(2) in the 734 child of the fork need to ensure that the child is protected 735 from deadlock. 736 737 Since the "fork-one" model results in duplicating only the 738 thread that called fork(), it is possible that at the time 739 of the call another thread in the parent owns a lock. This 740 thread is not duplicated in the child, so no thread will 741 unlock this lock in the child. Deadlock occurs if the sin- 742 gle thread in the child needs this lock. 743 744 The problem is more serious with locks in libraries. Since 745 a library writer does not know if the application using the 746 library calls fork(), the library must protect itself from 747 such a deadlock scenario. If the application that links 748 with this library calls fork() and does not call exec() in 749 the child, and if it needs a library lock that may be held 750 by some other thread in the parent that is inside the 751 library at the time of the fork, the application deadlocks 752 inside the library. 753 */ 754 755 static void 756 linetrace_ext_fork_prologue (const char *variant, char * n_lineage, int *following_fork) 757 { 758 TprintfT (DBG_LT0, "linetrace_ext_fork_prologue; variant=%s; new_lineage=%s; follow=%d\n", 759 variant, n_lineage, *following_fork); 760 __collector_env_print ("fork_prologue start"); 761 if (dbg_current_mode != FOLLOW_NONE) 762 TprintfT (DBG_LT0, "linetrace_ext_fork_prologue(%s) ERROR: dbg_current_mode=%d, changing to FOLLOW_FORK!\n", 763 variant, dbg_current_mode); 764 dbg_current_mode = FOLLOW_ON; 765 if (__collector_strncmp ((char *) variant, "clone", sizeof ("clone") - 1) == 0) 766 { 767 __collector_mutex_lock (&clone_lineage_lock); 768 CALL_UTIL (snprintf)(n_lineage, LT_MAXNAMELEN, "%s_C%d", curr_lineage, ++clone_linenum); 769 __collector_mutex_unlock (&clone_lineage_lock); 770 } 771 else 772 { 773 __collector_mutex_lock (&fork_lineage_lock); 774 CALL_UTIL (snprintf)(n_lineage, LT_MAXNAMELEN, "%s_f%d", curr_lineage, ++fork_linenum); 775 __collector_mutex_unlock (&fork_lineage_lock); 776 } 777 *following_fork = check_follow_fork (); 778 779 /* write message before suspending, or it won't be written */ 780 hrtime_t ts = GETRELTIME (); 781 TprintfT (DBG_LT0, "linetrace_ext_fork_prologue; variant=%s; new_lineage=%s; follow=%d\n", 782 variant, n_lineage, *following_fork); 783 __collector_log_write ("<event kind=\"%s\" tstamp=\"%u.%09u\" variant=\"%s\" lineage=\"%s\" follow=\"%d\"/>\n", 784 SP_JCMD_DESC_START, 785 (unsigned) (ts / NANOSEC), (unsigned) (ts % NANOSEC), 786 variant, n_lineage, *following_fork); 787 __collector_ext_dispatcher_thread_timer_suspend (); 788 __collector_ext_hwc_lwp_suspend (); 789 __collector_env_print ("fork_prologue end"); 790 } 791 792 static void 793 linetrace_ext_fork_epilogue (const char *variant, const pid_t ret, char * n_lineage, int *following_fork) 794 { 795 if (dbg_current_mode == FOLLOW_NONE) 796 TprintfT (DBG_LT0, "linetrace_ext_fork_epilogue(%s) ERROR: dbg_current_mode=%d!\n", 797 variant, dbg_current_mode); 798 /* compute descendant experiment name */ 799 char new_exp_name[LT_MAXPATHLEN]; 800 /* save exp_name to global var */ 801 if (!build_experiment_path (new_exp_name, sizeof (new_exp_name), n_lineage)) 802 TprintfT (DBG_LT0, "linetrace_ext_fork_epilogue(%s): ERROR SP_COLLECTOR_EXPNAME not set\n", n_lineage); 803 TprintfT (DBG_LT0, "linetrace_ext_fork_epilogue(%s):%d() returned %d %s; child experiment name = %s\n", 804 variant, *following_fork, ret, (ret ? "parent" : "child"), new_exp_name); 805 if (ret == 0) 806 { 807 /* *************************************child */ 808 __collector_env_print ("fork_epilogue child at start"); 809 /* start a new line */ 810 fork_linenum = 0; 811 __collector_mutex_init (&fork_lineage_lock); 812 clone_linenum = 0; 813 __collector_mutex_init (&clone_lineage_lock); 814 __collector_env_update (NULL); 815 __collector_env_print ("fork_epilogue child after env_update"); 816 __collector_clean_state (); 817 __collector_env_print ("fork_epilogue child after clean_slate"); 818 __collector_line_cleanup (); 819 __collector_env_print ("fork_epilogue child after line_cleanup"); 820 if (*following_fork) 821 { 822 /* stop recording this experiment, but preserve env vars */ 823 linetrace_dormant (); 824 __collector_env_print ("fork_epilogue child after linetrace_dormant"); 825 826 //static char exp_name_env[LT_MAXPATHLEN]; 827 char * exp_name_env = CALL_UTIL (calloc)(LT_MAXPATHLEN, 1); 828 CALL_UTIL (snprintf)(exp_name_env, LT_MAXPATHLEN, "%s=%s", SP_COLLECTOR_EXPNAME, new_exp_name); 829 CALL_UTIL (putenv)(exp_name_env); 830 831 const char *params = CALL_UTIL (getenv)(SP_COLLECTOR_PARAMS); 832 int ret; 833 if (new_exp_name == NULL) 834 TprintfT (DBG_LT0, "linetrace_ext_fork_epilogue: ERROR: getenv(%s) undefined -- new expt aborted!\n", 835 SP_COLLECTOR_EXPNAME); 836 else if (params == NULL) 837 TprintfT (DBG_LT0, "linetrace_ext_fork_epilogue: ERROR: getenv(%s) undefined -- new expt aborted!\n", 838 SP_COLLECTOR_PARAMS); 839 else if ((ret = __collector_open_experiment (new_exp_name, params, SP_ORIGIN_FORK))) 840 TprintfT (DBG_LT0, "linetrace_ext_fork_epilogue: ERROR: '%s' open failed, ret=%d\n", 841 new_exp_name, ret); 842 else 843 TprintfT (DBG_LT0, "linetrace_ext_fork_epilogue: opened(%s)\n", new_exp_name); 844 TprintfT (DBG_LT0, "linetrace_ext_fork_epilogue(%s) returning to *child*\n", variant); 845 } 846 else 847 { 848 /* disable current and further linetrace experiment resumption */ 849 TprintfT (DBG_LT0, "linetrace_ext_fork_epilogue(%s) child calling line_close\n", variant); 850 __collector_ext_line_close (); 851 } 852 __collector_env_print ("fork_epilogue child at end"); 853 /* *************************************end child */ 854 } 855 else 856 { 857 /* *************************************parent */ 858 __collector_env_print ("fork_epilogue parent at start"); 859 __collector_ext_dispatcher_thread_timer_resume (); 860 __collector_ext_hwc_lwp_resume (); 861 hrtime_t ts = GETRELTIME (); 862 char msg[256 + LT_MAXPATHLEN]; 863 if (ret >= 0) 864 CALL_UTIL (snprintf)(msg, sizeof (msg), "pid=%d", ret); 865 else 866 { 867 /* delete stillborn experiment? */ 868 char errmsg[256]; 869 strerror_r (errno, errmsg, sizeof (errmsg)); 870 CALL_UTIL (snprintf)(msg, sizeof (msg), "err %s", errmsg); 871 } 872 __collector_log_write ("<event kind=\"%s\" tstamp=\"%u.%09u\" variant=\"%s\" lineage=\"%s\" follow=\"%d\" msg=\"%s\"/>\n", 873 SP_JCMD_DESC_STARTED, 874 (unsigned) (ts / NANOSEC), (unsigned) (ts % NANOSEC), 875 variant, n_lineage, *following_fork, msg); 876 /* environment remains set for collection */ 877 __collector_env_print ("fork_epilogue parent at end"); 878 /* *************************************end parent */ 879 } 880 dbg_current_mode = FOLLOW_NONE; 881 *following_fork = 0; 882 } 883 884 static char** 885 linetrace_ext_exec_prologue_end (const char *variant, const char* cmd_string, 886 char *const envp[], int following_exec) 887 { 888 char **coll_env; 889 TprintfT (DBG_LT0, "linetrace_ext_exec_prologue_end; variant=%s; cmd_string=%s; follow=%d\n", 890 variant, cmd_string, following_exec); 891 /* write message before suspending, or it won't be written */ 892 hrtime_t ts = GETRELTIME (); 893 __collector_log_write ("<event kind=\"%s\" tstamp=\"%u.%09u\" variant=\"%s\" lineage=\"%s\" follow=\"%d\" msg=\"%s\"/>\n", 894 SP_JCMD_EXEC_START, 895 (unsigned) (ts / NANOSEC), (unsigned) (ts % NANOSEC), 896 variant, new_lineage, following_exec, cmd_string); 897 if (following_exec) 898 { 899 coll_env = __collector_env_allocate (envp, 0); 900 __collector_env_update (coll_env); 901 extern char **environ; /* the process' actual environment */ 902 if (environ == envp) /* user selected process environment */ 903 environ = coll_env; 904 } 905 else 906 coll_env = (char**) envp; 907 __collector_env_printall ("linetrace_ext_exec_prologue_end", coll_env); 908 if (!CALL_UTIL (strstr)(variant, "posix_spawn")) 909 { 910 __collector_linetrace_shutdown_hwcs_6830763_XXXX = 1; 911 __collector_suspend_experiment ("suspend_for_exec"); 912 __collector_linetrace_shutdown_hwcs_6830763_XXXX = 0; 913 } 914 if (CALL_UTIL (strstr)(variant, "posix_spawn")) 915 { 916 __collector_ext_dispatcher_thread_timer_suspend (); 917 __collector_linetrace_shutdown_hwcs_6830763_XXXX = 1; 918 __collector_ext_hwc_lwp_suspend (); 919 __collector_linetrace_shutdown_hwcs_6830763_XXXX = 0; 920 } 921 return (coll_env); 922 } 923 924 static char** 925 linetrace_ext_exec_prologue (const char *variant, 926 const char* path, char *const argv[], 927 char *const envp[], int *following_exec) 928 { 929 char cmd_string[_POSIX_ARG_MAX] = {'\0'}; 930 931 if (dbg_current_mode != FOLLOW_NONE) 932 TprintfT (DBG_LT0, "linetrace_ext_exec_prologue() ERROR: dbg_current_mode=%d, changing to FOLLOW_EXEC!\n", dbg_current_mode); 933 dbg_current_mode = FOLLOW_ON; 934 *following_exec = check_follow_exec (path); 935 if (path != NULL) 936 { 937 /* escape any newline, " or \ characters in the exec command */ 938 TprintfT (DBG_LT3, "linetrace_ext_exec_prologue(): arg0=%s\n", path); 939 /* leave space in log message for terminator (and header) */ 940 __collector_strlcpy (cmd_string, path, sizeof (cmd_string)); 941 size_t len; 942 unsigned argn = 0; 943 if (argv[0]) 944 { 945 char *p; 946 while (((p = argv[++argn]) != 0) && 947 (len = __collector_strlen (cmd_string)) < sizeof (cmd_string) - 2) 948 { 949 cmd_string[len++] = ' '; 950 __collector_strlcpy (cmd_string + len, p, sizeof (cmd_string) - len); 951 } 952 } 953 } 954 TprintfT (DBG_LT0, "linetrace_ext_exec_prologue(%s), lineage=%s, follow=%d, prog=%s, path=%s \n", 955 variant, new_lineage, *following_exec, cmd_string, path); 956 return linetrace_ext_exec_prologue_end (variant, cmd_string, envp, *following_exec); 957 } 958 959 static void 960 linetrace_ext_exec_epilogue (const char *variant, char *const envp[], const int ret, int *following_exec) 961 { 962 /* For exec, this routine is only entered if the exec failed */ 963 /* However, posix_spawn() is expected to return */ 964 if (dbg_current_mode == FOLLOW_NONE) 965 TprintfT (DBG_LT0, "linetrace_ext_exec_epilogue() ERROR: dbg_current_mode=%d!\n", dbg_current_mode); 966 TprintfT (DBG_LT0, "linetrace_ext_exec_epilogue(%s):%d returned: %d, errno=%d\n", 967 variant, *following_exec, ret, errno); 968 if (!CALL_UTIL (strstr)(variant, "posix_spawn")) 969 { 970 __collector_linetrace_shutdown_hwcs_6830763_XXXX = 1; 971 __collector_resume_experiment (); 972 __collector_linetrace_shutdown_hwcs_6830763_XXXX = 0; 973 } 974 if (CALL_UTIL (strstr)(variant, "posix_spawn")) 975 { 976 __collector_ext_dispatcher_thread_timer_resume (); 977 __collector_linetrace_shutdown_hwcs_6830763_XXXX = 1; 978 __collector_ext_hwc_lwp_resume (); 979 __collector_linetrace_shutdown_hwcs_6830763_XXXX = 0; 980 } 981 hrtime_t ts = GETRELTIME (); 982 char msg[256]; 983 if (ret) 984 { 985 char errmsg[256]; 986 strerror_r (errno, errmsg, sizeof (errmsg)); 987 CALL_UTIL (snprintf)(msg, sizeof (msg), "err %s", errmsg); 988 } 989 else 990 CALL_UTIL (snprintf)(msg, sizeof (msg), "rc=%d", ret); 991 if (!CALL_UTIL (strstr)(variant, "posix_spawn")) 992 __collector_log_write ("<event kind=\"%s\" tstamp=\"%u.%09u\" variant=\"%s\" lineage=\"%s\" follow=\"%d\" msg=\"%s\"/>\n", 993 SP_JCMD_EXEC_ERROR, 994 (unsigned) (ts / NANOSEC), (unsigned) (ts % NANOSEC), 995 variant, new_lineage, *following_exec, msg); 996 if (envp == NULL) 997 TprintfT (DBG_LT0, "linetrace_ext_exec_epilogue() ERROR: envp NULL after %s!\n", variant); 998 dbg_current_mode = FOLLOW_NONE; 999 *following_exec = 0; 1000 } 1001 1002 static void 1003 linetrace_ext_combo_prologue (const char *variant, const char *cmd, int *following_combo) 1004 { 1005 char cmd_string[_POSIX_ARG_MAX] = {'\0'}; 1006 char execfile[_POSIX_ARG_MAX] = {'\0'}; 1007 1008 if (dbg_current_mode != FOLLOW_NONE) 1009 TprintfT (DBG_LT0, "linetrace_ext_combo_prologue() ERROR: dbg_current_mode=%d! changing to FOLLOW_ON\n", 1010 dbg_current_mode); 1011 dbg_current_mode = FOLLOW_ON; 1012 if (cmd != NULL) 1013 { 1014 /* extract executable name from combo command */ 1015 unsigned len = strcspn (cmd, " "); 1016 __collector_strlcpy (execfile, cmd, len + 1); 1017 1018 /* escape any newline, " or \ characters in the combo command */ 1019 /* leave space in log message for terminator (and header) */ 1020 __collector_strlcpy (cmd_string, cmd, sizeof (cmd_string)); 1021 } 1022 1023 *following_combo = check_follow_combo (execfile); 1024 TprintfT (DBG_LT0, "linetrace_ext_combo_prologue(%s) follow=%d, prog=%s\n\n", 1025 variant, *following_combo, cmd_string); 1026 1027 /* Construct the lineage string for the new image */ 1028 new_lineage[0] = 0; 1029 __collector_strcat (new_lineage, "XXX"); 1030 1031 /* write message before suspending, or it won't be written */ 1032 hrtime_t ts = GETRELTIME (); 1033 __collector_log_write ("<event kind=\"%s\" tstamp=\"%u.%09u\" variant=\"%s\" lineage=\"%s\" follow=\"%d\" msg=\"%s\"/>\n", 1034 SP_JCMD_DESC_START, 1035 (unsigned) (ts / NANOSEC), (unsigned) (ts % NANOSEC), 1036 variant, new_lineage, *following_combo, cmd_string); 1037 if (*following_combo) 1038 { 1039 __collector_env_update (NULL); 1040 TprintfT (DBG_LT0, "linetrace_ext_combo_prologue(): Following %s(\"%s\")\n", variant, execfile); 1041 } 1042 __collector_ext_dispatcher_thread_timer_suspend (); 1043 __collector_linetrace_shutdown_hwcs_6830763_XXXX = 1; 1044 __collector_ext_hwc_lwp_suspend (); 1045 __collector_linetrace_shutdown_hwcs_6830763_XXXX = 0; 1046 } 1047 1048 static void 1049 linetrace_ext_combo_epilogue (const char *variant, const int ret, int *following_combo) 1050 { 1051 if (dbg_current_mode == FOLLOW_NONE) 1052 TprintfT (DBG_LT0, "linetrace_ext_combo_epilogue() ERROR: dbg_current_mode=FOLLOW_NONE\n"); 1053 TprintfT (DBG_LT0, "linetrace_ext_combo_epilogue(%s):%d() returned %d\n", 1054 variant, *following_combo, ret); 1055 __collector_ext_dispatcher_thread_timer_resume (); 1056 __collector_linetrace_shutdown_hwcs_6830763_XXXX = 1; 1057 __collector_ext_hwc_lwp_resume (); 1058 __collector_linetrace_shutdown_hwcs_6830763_XXXX = 0; 1059 hrtime_t ts = GETRELTIME (); 1060 __collector_log_write ("<event kind=\"%s\" tstamp=\"%u.%09u\" variant=\"%s\" follow=\"%d\" msg=\"rc=%d\"/>\n", 1061 SP_JCMD_DESC_STARTED, 1062 (unsigned) (ts / NANOSEC), (unsigned) (ts % NANOSEC), 1063 variant, *following_combo, ret); 1064 1065 dbg_current_mode = FOLLOW_NONE; 1066 *following_combo = 0; 1067 } 1068 1069 /*------------------------------------------------------------- fork */ 1070 pid_t fork () __attribute__ ((weak, alias ("__collector_fork"))); 1071 pid_t _fork () __attribute__ ((weak, alias ("__collector_fork"))); 1072 1073 pid_t 1074 __collector_fork (void) 1075 { 1076 pid_t ret; 1077 if (NULL_PTR (fork)) 1078 { 1079 TprintfT (DBG_LT0, "__collector_fork() calling init_lineage_intf()\n"); 1080 init_lineage_intf (); 1081 } 1082 __collector_env_print ("__collector_fork start"); 1083 int * guard = NULL; 1084 int combo_flag = (line_mode == LM_TRACK_LINEAGE) ? ((CHCK_REENTRANCE (guard)) ? 1 : 0) : 0; 1085 TprintfT (DBG_LT0, "__collector_fork() interposition: line_mode=%d combo=%d\n", 1086 line_mode, combo_flag); 1087 if ((line_mode != LM_TRACK_LINEAGE) || combo_flag) 1088 { 1089 TprintfT (DBG_LT0, "__collector_fork() not following, returning CALL_REAL(fork)()\n"); 1090 return CALL_REAL (fork)(); 1091 } 1092 int following_fork = 0; 1093 linetrace_ext_fork_prologue ("fork", new_lineage, &following_fork); 1094 1095 /* since libpthread/fork ends up calling fork1, it's a combo */ 1096 PUSH_REENTRANCE (guard); 1097 ret = CALL_REAL (fork)(); 1098 POP_REENTRANCE (guard); 1099 linetrace_ext_fork_epilogue ("fork", ret, new_lineage, &following_fork); 1100 return ret; 1101 } 1102 1103 /*------------------------------------------------------------- vfork */ 1104 /* vfork interposition in the usual sense is not possible, since vfork(2) 1105 relies on specifics of the stack frames in the parent and child which 1106 only work when the child's exec (or _exit) are in the same stack frame 1107 as the vfork: this isn't the case when there's interposition on exec. 1108 As a workaround, the interposing vfork calls fork1 instead of the real 1109 vfork. Note that fork1 is somewhat less efficient than vfork, and requires 1110 additional memory, which may result in a change of application behaviour 1111 when libcollector is loaded (even when collection is not active), 1112 affecting not only direct use of vfork by the subject application, 1113 but also indirect use through system, popen, and the other combos. 1114 */ 1115 pid_t vfork () __attribute__ ((weak, alias ("__collector_vfork"))); 1116 pid_t _vfork () __attribute__ ((weak, alias ("__collector_vfork"))); 1117 1118 pid_t 1119 __collector_vfork (void) 1120 { 1121 if (NULL_PTR (vfork)) 1122 init_lineage_intf (); 1123 1124 int * guard = NULL; 1125 int combo_flag = (line_mode == LM_TRACK_LINEAGE) ? ((CHCK_REENTRANCE (guard)) ? 1 : 0) : 0; 1126 1127 TprintfT (DBG_LT0, "__collector_vfork() interposing: line_mode=%d combo=%d\n", 1128 line_mode, combo_flag); 1129 if ((line_mode != LM_TRACK_LINEAGE) || combo_flag) 1130 return CALL_REAL (fork)(); 1131 1132 /* this warning is also appropriate for combos which use vfork, 1133 however, let's assume this is achieved elsewhere */ 1134 (void) __collector_log_write ("<event kind=\"%s\" id=\"%d\">%s</event>\n", SP_JCMD_CWARN, 1135 COL_WARN_VFORK, "fork"); 1136 1137 char new_lineage[LT_MAXNAMELEN]; 1138 new_lineage[0] = 0; 1139 int following_fork = 0; 1140 linetrace_ext_fork_prologue ("vfork", new_lineage, &following_fork); 1141 1142 pid_t ret = CALL_REAL (fork)(); 1143 linetrace_ext_fork_epilogue ("vfork", ret, new_lineage, &following_fork); 1144 return ret; 1145 } 1146 1147 /*------------------------------------------------------------- execve */ 1148 int execve () __attribute__ ((weak, alias ("__collector_execve"))); 1149 1150 int 1151 __collector_execve (const char* path, char *const argv[], char *const envp[]) 1152 { 1153 static char **coll_env = NULL; /* environment for collection */ 1154 if (NULL_PTR (execve)) 1155 init_lineage_intf (); 1156 int * guard = NULL; 1157 int combo_flag = (line_mode == LM_TRACK_LINEAGE) ? ((CHCK_REENTRANCE (guard)) ? 1 : 0) : 0; 1158 TprintfT (DBG_LT0, 1159 "__collector_execve(path=%s, argv[0]=%s, env[0]=%s) interposing: line_mode=%d combo=%d\n", 1160 path ? path : "NULL", 1161 argv ? (argv[0] ? argv[0] : "NULL") : "NULL", 1162 envp ? (envp[0] ? envp[0] : "NULL") : "NULL", 1163 line_mode, combo_flag); 1164 if (line_mode == LM_CLOSED) /* ensure collection environment is sanitised */ 1165 __collector_env_unset ((char**) envp); 1166 if (line_mode != LM_TRACK_LINEAGE || combo_flag) 1167 return CALL_REAL (execve)(path, argv, envp); 1168 1169 int following_exec = 0; 1170 coll_env = linetrace_ext_exec_prologue ("execve", path, argv, envp, &following_exec); 1171 TprintfT (DBG_LT2, "__collector_execve(): coll_env=0x%p\n", coll_env); 1172 __collector_env_printall ("__collector_execve", coll_env); 1173 int ret = CALL_REAL (execve)(path, argv, coll_env); 1174 linetrace_ext_exec_epilogue ("execve", envp, ret, &following_exec); 1175 return ret; 1176 } 1177 1178 int execvp () __attribute__ ((weak, alias ("__collector_execvp"))); 1179 1180 int 1181 __collector_execvp (const char* file, char *const argv[]) 1182 { 1183 extern char **environ; /* the process' actual environment */ 1184 char ** envp = environ; 1185 if (NULL_PTR (execvp)) 1186 init_lineage_intf (); 1187 int * guard = NULL; 1188 int combo_flag = (line_mode == LM_TRACK_LINEAGE) ? ((CHCK_REENTRANCE (guard)) ? 1 : 0) : 0; 1189 TprintfT (DBG_LT0, 1190 "__collector_execvp(file=%s, argv[0]=%s) interposing: line_mode=%d combo=%d\n", 1191 file ? file : "NULL", argv ? (argv[0] ? argv[0] : "NULL") : "NULL", 1192 line_mode, combo_flag); 1193 if (line_mode == LM_CLOSED) /* ensure collection environment is sanitised */ 1194 __collector_env_unset ((char**) envp); 1195 if ((line_mode != LM_TRACK_LINEAGE) || combo_flag) 1196 return CALL_REAL (execvp)(file, argv); 1197 1198 int following_exec = 0; 1199 #ifdef DEBUG 1200 char **coll_env = /* environment for collection */ 1201 #endif /* DEBUG */ 1202 linetrace_ext_exec_prologue ("execvp", file, argv, envp, &following_exec); 1203 TprintfT (DBG_LT0, "__collector_execvp(): coll_env=0x%p\n", coll_env); 1204 1205 int ret = CALL_REAL (execvp)(file, argv); 1206 linetrace_ext_exec_epilogue ("execvp", envp, ret, &following_exec); 1207 return ret; 1208 } 1209 1210 int execv () __attribute__ ((weak, alias ("__collector_execv"))); 1211 1212 int 1213 __collector_execv (const char* path, char *const argv[]) 1214 { 1215 int ret; 1216 extern char **environ; /* the process' actual environment */ 1217 char ** envp = environ; 1218 TprintfT (DBG_LT0, "__collector_execv(path=%s, argv[0]=%s) interposing: line_mode=%d combo=%d\n", 1219 path ? path : "NULL", argv ? (argv[0] ? argv[0] : "NULL") : "NULL", 1220 line_mode, get_combo_flag ()); 1221 1222 ret = __collector_execve (path, argv, envp); 1223 return ret; 1224 } 1225 1226 int execle (const char* path, const char *arg0, ...) __attribute__ ((weak, alias ("__collector_execle"))); 1227 1228 int 1229 __collector_execle (const char* path, const char *arg0, ...) 1230 { 1231 TprintfT (DBG_LT0, 1232 "__collector_execle(path=%s, arg0=%s) interposing: line_mode=%d combo=%d\n", 1233 path ? path : "NULL", arg0 ? arg0 : "NULL", 1234 line_mode, get_combo_flag ()); 1235 1236 char **argp; 1237 va_list args; 1238 char **argvec; 1239 register char **environmentp; 1240 int nargs = 0; 1241 char *nextarg; 1242 1243 va_start (args, arg0); 1244 while (va_arg (args, char *) != (char *) 0) 1245 nargs++; 1246 1247 /* 1248 * save the environment pointer, which is at the end of the 1249 * variable argument list 1250 */ 1251 environmentp = va_arg (args, char **); 1252 va_end (args); 1253 1254 /* 1255 * load the arguments in the variable argument list 1256 * into the argument vector, and add the terminating null pointer 1257 */ 1258 va_start (args, arg0); 1259 /* workaround for bugid 1242839 */ 1260 argvec = (char **) alloca ((size_t) ((nargs + 2) * sizeof (char *))); 1261 argp = argvec; 1262 *argp++ = (char *) arg0; 1263 while ((nextarg = va_arg (args, char *)) != (char *) 0) 1264 *argp++ = nextarg; 1265 va_end (args); 1266 *argp = (char *) 0; 1267 return __collector_execve (path, argvec, environmentp); 1268 } 1269 1270 int execlp (const char* file, const char *arg0, ...) __attribute__ ((weak, alias ("__collector_execlp"))); 1271 1272 int 1273 __collector_execlp (const char* file, const char *arg0, ...) 1274 { 1275 TprintfT (DBG_LT0, 1276 "__collector_execlp(file=%s, arg0=%s) interposing: line_mode=%d combo=%d\n", 1277 file ? file : "NULL", arg0 ? arg0 : "NULL", 1278 line_mode, get_combo_flag ()); 1279 char **argp; 1280 va_list args; 1281 char **argvec; 1282 int nargs = 0; 1283 char *nextarg; 1284 1285 va_start (args, arg0); 1286 while (va_arg (args, char *) != (char *) 0) 1287 nargs++; 1288 va_end (args); 1289 1290 /* 1291 * load the arguments in the variable argument list 1292 * into the argument vector and add the terminating null pointer 1293 */ 1294 va_start (args, arg0); 1295 1296 /* workaround for bugid 1242839 */ 1297 argvec = (char **) alloca ((size_t) ((nargs + 2) * sizeof (char *))); 1298 argp = argvec; 1299 *argp++ = (char *) arg0; 1300 while ((nextarg = va_arg (args, char *)) != (char *) 0) 1301 *argp++ = nextarg; 1302 va_end (args); 1303 *argp = (char *) 0; 1304 return __collector_execvp (file, argvec); 1305 } 1306 1307 int execl (const char* path, const char *arg0, ...) __attribute__ ((weak, alias ("__collector_execl"))); 1308 1309 int 1310 __collector_execl (const char* path, const char *arg0, ...) 1311 { 1312 TprintfT (DBG_LT0, 1313 "__collector_execl(path=%s, arg0=%s) interposing: line_mode=%d combo=%d\n", 1314 path ? path : "NULL", arg0 ? arg0 : "NULL", 1315 line_mode, get_combo_flag ()); 1316 char **argp; 1317 va_list args; 1318 char **argvec; 1319 extern char **environ; 1320 int nargs = 0; 1321 char *nextarg; 1322 va_start (args, arg0); 1323 while (va_arg (args, char *) != (char *) 0) 1324 nargs++; 1325 va_end (args); 1326 1327 /* 1328 * load the arguments in the variable argument list 1329 * into the argument vector and add the terminating null pointer 1330 */ 1331 va_start (args, arg0); 1332 1333 /* workaround for bugid 1242839 */ 1334 argvec = (char **) alloca ((size_t) ((nargs + 2) * sizeof (char *))); 1335 argp = argvec; 1336 *argp++ = (char *) arg0; 1337 while ((nextarg = va_arg (args, char *)) != (char *) 0) 1338 *argp++ = nextarg; 1339 va_end (args); 1340 *argp = (char *) 0; 1341 return __collector_execve (path, argvec, environ); 1342 } 1343 1344 #include <spawn.h> 1345 1346 /*-------------------------------------------------------- posix_spawn */ 1347 #if ARCH(Intel) 1348 // map interposed symbol versions 1349 static int 1350 __collector_posix_spawn_symver (int(real_posix_spawn) (), 1351 pid_t *pidp, const char *path, 1352 const posix_spawn_file_actions_t *file_actions, 1353 const posix_spawnattr_t *attrp, 1354 char *const argv[], char *const envp[]); 1355 1356 SYMVER_ATTRIBUTE (__collector_posix_spawn_2_15, posix_spawn@@GLIBC_2.15) 1357 int 1358 __collector_posix_spawn_2_15 (pid_t *pidp, const char *path, 1359 const posix_spawn_file_actions_t *file_actions, 1360 const posix_spawnattr_t *attrp, 1361 char *const argv[], char *const envp[]) 1362 { 1363 TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_posix_spawn_2_15@%p(path=%s, argv[0]=%s, env[0]=%s)\n", 1364 CALL_REAL (posix_spawn_2_15), path ? path : "NULL", argv ? (argv[0] ? argv[0] : "NULL") : "NULL", envp ? (envp[0] ? envp[0] : "NULL") : "NULL"); 1365 if (NULL_PTR (posix_spawn)) 1366 init_lineage_intf (); 1367 return __collector_posix_spawn_symver (CALL_REAL (posix_spawn_2_15), pidp, 1368 path, file_actions, attrp, argv, envp); 1369 } 1370 1371 #if WSIZE(32) 1372 SYMVER_ATTRIBUTE (__collector_posix_spawn_2_2, posix_spawn@GLIBC_2.2) 1373 int 1374 __collector_posix_spawn_2_2 (pid_t *pidp, const char *path, 1375 const posix_spawn_file_actions_t *file_actions, 1376 const posix_spawnattr_t *attrp, 1377 char *const argv[], char *const envp[]) 1378 { 1379 TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_posix_spawn_2_2@%p(path=%s, argv[0]=%s, env[0]=%s)\n", 1380 CALL_REAL (posix_spawn_2_2), path ? path : "NULL", argv ? (argv[0] ? argv[0] : "NULL") : "NULL", envp ? (envp[0] ? envp[0] : "NULL") : "NULL"); 1381 if (NULL_PTR (posix_spawn)) 1382 init_lineage_intf (); 1383 return __collector_posix_spawn_symver (CALL_REAL (posix_spawn_2_2), pidp, 1384 path, file_actions, attrp, argv, envp); 1385 } 1386 1387 #else /* ^WSIZE(32) */ 1388 SYMVER_ATTRIBUTE (__collector_posix_spawn_2_2_5, posix_spawn@GLIBC_2.2.5) 1389 int 1390 __collector_posix_spawn_2_2_5 (pid_t *pidp, const char *path, 1391 const posix_spawn_file_actions_t *file_actions, 1392 const posix_spawnattr_t *attrp, 1393 char *const argv[], char *const envp[]) 1394 { 1395 TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_posix_spawn_2_2_5@%p(path=%s, argv[0]=%s, env[0]=%s)\n", 1396 CALL_REAL (posix_spawn_2_2_5), path ? path : "NULL", argv ? (argv[0] ? argv[0] : "NULL") : "NULL", envp ? (envp[0] ? envp[0] : "NULL") : "NULL"); 1397 if (NULL_PTR (posix_spawn)) 1398 init_lineage_intf (); 1399 return __collector_posix_spawn_symver (CALL_REAL (posix_spawn_2_2_5), pidp, 1400 path, file_actions, attrp, argv, envp); 1401 } 1402 #endif /* ^WSIZE(32) */ 1403 1404 static int 1405 __collector_posix_spawn_symver (int(real_posix_spawn) (), 1406 #else /* ^ARCH(Intel) */ 1407 int 1408 __collector_posix_spawn ( 1409 #endif /* ARCH() */ 1410 pid_t *pidp, const char *path, 1411 const posix_spawn_file_actions_t *file_actions, 1412 const posix_spawnattr_t *attrp, 1413 char *const argv[], char *const envp[]) 1414 { 1415 int ret; 1416 static char **coll_env = NULL; /* environment for collection */ 1417 if (NULL_PTR (posix_spawn)) 1418 init_lineage_intf (); 1419 if (NULL_PTR (posix_spawn)) 1420 { 1421 TprintfT (DBG_LT0, "__collector_posix_spawn(path=%s) interposing: ERROR, posix_spawn() not found by dlsym\n", 1422 path ? path : "NULL"); 1423 return -1; /* probably should set errno */ 1424 } 1425 int * guard = NULL; 1426 int combo_flag = (line_mode == LM_TRACK_LINEAGE) ? ((CHCK_REENTRANCE (guard)) ? 1 : 0) : 0; 1427 TprintfT (DBG_LT0, "__collector_posix_spawn(path=%s, argv[0]=%s, env[0]=%s) interposing: line_mode=%d combo=%d\n", 1428 path ? path : "NULL", argv ? (argv[0] ? argv[0] : "NULL") : "NULL", envp ? (envp[0] ? envp[0] : "NULL") : "NULL", line_mode, combo_flag); 1429 if (line_mode == LM_CLOSED) /* ensure collection environment is sanitised */ 1430 __collector_env_unset ((char**) envp); 1431 1432 if ((line_mode != LM_TRACK_LINEAGE) || combo_flag) 1433 { 1434 #if ARCH(Intel) 1435 return (real_posix_spawn) (pidp, path, file_actions, attrp, argv, envp); 1436 #else 1437 return CALL_REAL (posix_spawn)(pidp, path, file_actions, attrp, argv, envp); 1438 #endif 1439 } 1440 int following_exec = 0; 1441 coll_env = linetrace_ext_exec_prologue ("posix_spawn", path, argv, envp, &following_exec); 1442 TprintfT (DBG_LT0, "__collector_posix_spawn(): coll_env=0x%p\n", coll_env); 1443 __collector_env_printall ("__collector_posix_spawn", coll_env); 1444 PUSH_REENTRANCE (guard); 1445 #if ARCH(Intel) 1446 ret = (real_posix_spawn) (pidp, path, file_actions, attrp, argv, coll_env); 1447 #else 1448 ret = CALL_REAL (posix_spawn)(pidp, path, file_actions, attrp, argv, coll_env); 1449 #endif 1450 POP_REENTRANCE (guard); 1451 linetrace_ext_exec_epilogue ("posix_spawn", envp, ret, &following_exec); 1452 return ret; 1453 } 1454 1455 /*-------------------------------------------------------- posix_spawnp */ 1456 #if ARCH(Intel) 1457 // map interposed symbol versions 1458 1459 static int 1460 __collector_posix_spawnp_symver (int(real_posix_spawnp) (), pid_t *pidp, 1461 const char *path, 1462 const posix_spawn_file_actions_t *file_actions, 1463 const posix_spawnattr_t *attrp, 1464 char *const argv[], char *const envp[]); 1465 1466 SYMVER_ATTRIBUTE (__collector_posix_spawnp_2_15, posix_spawnp@@GLIBC_2.15) 1467 int // Common interposition 1468 __collector_posix_spawnp_2_15 (pid_t *pidp, const char *path, 1469 const posix_spawn_file_actions_t *file_actions, 1470 const posix_spawnattr_t *attrp, 1471 char *const argv[], char *const envp[]) 1472 { 1473 TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_posix_spawnp_2_15@%p(path=%s, argv[0]=%s, env[0]=%s)\n", 1474 CALL_REAL (posix_spawnp_2_15), path ? path : "NULL", argv ? (argv[0] ? argv[0] : "NULL") : "NULL", envp ? (envp[0] ? envp[0] : "NULL") : "NULL"); 1475 if (NULL_PTR (posix_spawnp)) 1476 init_lineage_intf (); 1477 return __collector_posix_spawnp_symver (CALL_REAL (posix_spawnp_2_15), pidp, 1478 path, file_actions, attrp, argv, envp); 1479 } 1480 1481 #if WSIZE(32) 1482 1483 SYMVER_ATTRIBUTE (__collector_posix_spawnp_2_2, posix_spawnp@GLIBC_2.2) 1484 int 1485 __collector_posix_spawnp_2_2 (pid_t *pidp, const char *path, 1486 const posix_spawn_file_actions_t *file_actions, 1487 const posix_spawnattr_t *attrp, 1488 char *const argv[], char *const envp[]) 1489 { 1490 TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_posix_spawnp_2_2@%p(path=%s, argv[0]=%s, env[0]=%s)\n", 1491 CALL_REAL (posix_spawnp_2_2), path ? path : "NULL", argv ? (argv[0] ? argv[0] : "NULL") : "NULL", envp ? (envp[0] ? envp[0] : "NULL") : "NULL"); 1492 if (NULL_PTR (posix_spawnp)) 1493 init_lineage_intf (); 1494 return __collector_posix_spawnp_symver (CALL_REAL (posix_spawnp_2_2), pidp, 1495 path, file_actions, attrp, argv, envp); 1496 } 1497 1498 #else /* ^WSIZE(32) */ 1499 SYMVER_ATTRIBUTE (__collector_posix_spawnp_2_2_5, posix_spawnp@GLIBC_2.2.5) 1500 int 1501 __collector_posix_spawnp_2_2_5 (pid_t *pidp, const char *path, 1502 const posix_spawn_file_actions_t *file_actions, 1503 const posix_spawnattr_t *attrp, 1504 char *const argv[], char *const envp[]) 1505 { 1506 TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_posix_spawnp_2_2_5@%p(path=%s, argv[0]=%s, env[0]=%s)\n", 1507 CALL_REAL (posix_spawnp_2_2_5), path ? path : "NULL", argv ? (argv[0] ? argv[0] : "NULL") : "NULL", envp ? (envp[0] ? envp[0] : "NULL") : "NULL"); 1508 if (NULL_PTR (posix_spawnp)) 1509 init_lineage_intf (); 1510 return __collector_posix_spawnp_symver (CALL_REAL (posix_spawnp_2_2_5), pidp, 1511 path, file_actions, attrp, argv, envp); 1512 } 1513 1514 #endif /* ^WSIZE(32) */ 1515 1516 static int 1517 __collector_posix_spawnp_symver (int(real_posix_spawnp) (), 1518 #else /* ^ARCH(Intel) */ 1519 int 1520 __collector_posix_spawnp ( 1521 #endif /* ARCH() */ 1522 pid_t *pidp, const char *path, 1523 const posix_spawn_file_actions_t *file_actions, 1524 const posix_spawnattr_t *attrp, 1525 char *const argv[], char *const envp[]){ 1526 int ret; 1527 static char **coll_env = NULL; /* environment for collection */ 1528 if (NULL_PTR (posix_spawnp)) 1529 init_lineage_intf (); 1530 if (NULL_PTR (posix_spawnp)) 1531 { 1532 TprintfT (DBG_LT0, "__collector_posix_spawnp(path=%s) interposing: ERROR, posix_spawnp() not found by dlsym\n", 1533 path ? path : "NULL"); 1534 return -1; /* probably should set errno */ 1535 } 1536 int * guard = NULL; 1537 int combo_flag = (line_mode == LM_TRACK_LINEAGE) ? ((CHCK_REENTRANCE (guard)) ? 1 : 0) : 0; 1538 TprintfT (DBG_LT0, "__collector_posix_spawnp(path=%s, argv[0]=%s, env[0]=%s) interposing: line_mode=%d combo=%d\n", 1539 path ? path : "NULL", argv ? (argv[0] ? argv[0] : "NULL") : "NULL", 1540 envp ? (envp[0] ? envp[0] : "NULL") : "NULL", line_mode, combo_flag); 1541 1542 if (line_mode == LM_CLOSED) /* ensure collection environment is sanitised */ 1543 __collector_env_unset ((char**) envp); 1544 if (line_mode != LM_TRACK_LINEAGE || combo_flag) 1545 { 1546 #if ARCH(Intel) 1547 return (real_posix_spawnp) (pidp, path, file_actions, attrp, argv, envp); 1548 #else 1549 return CALL_REAL (posix_spawnp)(pidp, path, file_actions, attrp, argv, envp); 1550 #endif 1551 } 1552 int following_exec = 0; 1553 coll_env = linetrace_ext_exec_prologue ("posix_spawnp", path, argv, envp, &following_exec); 1554 TprintfT (DBG_LT0, "__collector_posix_spawnp(): coll_env=0x%p\n", coll_env); 1555 __collector_env_printall ("__collector_posix_spawnp", coll_env); 1556 PUSH_REENTRANCE (guard); 1557 #if ARCH(Intel) 1558 ret = (real_posix_spawnp) (pidp, path, file_actions, attrp, argv, coll_env); 1559 #else 1560 ret = CALL_REAL (posix_spawnp)(pidp, path, file_actions, attrp, argv, coll_env); 1561 #endif 1562 POP_REENTRANCE (guard); 1563 linetrace_ext_exec_epilogue ("posix_spawnp", envp, ret, &following_exec); 1564 return ret; 1565 } 1566 1567 /*------------------------------------------------------------- system */ 1568 int system () __attribute__ ((weak, alias ("__collector_system"))); 1569 1570 int 1571 __collector_system (const char *cmd) 1572 { 1573 if (NULL_PTR (system)) 1574 init_lineage_intf (); 1575 TprintfT (DBG_LT0, 1576 "__collector_system(cmd=%s) interposing: line_mode=%d combo=%d\n", 1577 cmd ? cmd : "NULL", line_mode, get_combo_flag ()); 1578 int *guard = NULL; 1579 if (line_mode == LM_TRACK_LINEAGE) 1580 INIT_REENTRANCE (guard); 1581 if (guard == NULL) 1582 return CALL_REAL (system)(cmd); 1583 int following_combo = 0; 1584 linetrace_ext_combo_prologue ("system", cmd, &following_combo); 1585 PUSH_REENTRANCE (guard); 1586 int ret = CALL_REAL (system)(cmd); 1587 POP_REENTRANCE (guard); 1588 linetrace_ext_combo_epilogue ("system", ret, &following_combo); 1589 return ret; 1590 } 1591 1592 /*------------------------------------------------------------- popen */ 1593 // map interposed symbol versions 1594 #if ARCH(Intel) && WSIZE(32) 1595 static FILE * 1596 __collector_popen_symver (FILE*(real_popen) (), const char *cmd, const char *mode); 1597 1598 SYMVER_ATTRIBUTE (__collector_popen_2_1, popen@@GLIBC_2.1) 1599 FILE * 1600 __collector_popen_2_1 (const char *cmd, const char *mode) 1601 { 1602 if (NULL_PTR (popen)) 1603 init_lineage_intf (); 1604 TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_popen_2_1@%p\n", CALL_REAL (popen_2_1)); 1605 return __collector_popen_symver (CALL_REALF (popen_2_1), cmd, mode); 1606 } 1607 1608 SYMVER_ATTRIBUTE (__collector_popen_2_0, popen@GLIBC_2.0) 1609 FILE * 1610 __collector_popen_2_0 (const char *cmd, const char *mode) 1611 { 1612 if (NULL_PTR (popen)) 1613 init_lineage_intf (); 1614 TprintfT (DBG_LTT, "linetrace: GLIBC: __collector_popen_2_0@%p\n", CALL_REAL (popen_2_0)); 1615 return __collector_popen_symver (CALL_REALF (popen_2_0), cmd, mode); 1616 } 1617 1618 SYMVER_ATTRIBUTE (__collector__popen_2_1, _popen@@GLIBC_2.1) 1619 FILE * 1620 __collector__popen_2_1 (const char *cmd, const char *mode) 1621 { 1622 if (NULL_PTR (popen)) 1623 init_lineage_intf (); 1624 TprintfT (DBG_LTT, "linetrace: GLIBC: __collector__popen_2_1@%p\n", CALL_REAL (popen_2_1)); 1625 return __collector_popen_symver (CALL_REALF (popen_2_1), cmd, mode); 1626 } 1627 1628 SYMVER_ATTRIBUTE (__collector__popen_2_0, _popen@GLIBC_2.0) 1629 FILE * 1630 __collector__popen_2_0 (const char *cmd, const char *mode) 1631 { 1632 if (NULL_PTR (popen)) 1633 init_lineage_intf (); 1634 return __collector_popen_symver (CALL_REALF (popen_2_0), cmd, mode); 1635 } 1636 #else // WSIZE(64) 1637 FILE * popen () __attribute__ ((weak, alias ("__collector_popen"))); 1638 #endif 1639 1640 #if ARCH(Intel) && WSIZE(32) 1641 static FILE * 1642 __collector_popen_symver (FILE*(real_popen) (), const char *cmd, const char *mode) 1643 #else 1644 1645 FILE * 1646 __collector_popen (const char *cmd, const char *mode) 1647 #endif 1648 { 1649 FILE *ret; 1650 if (NULL_PTR (popen)) 1651 init_lineage_intf (); 1652 TprintfT (DBG_LT0, 1653 "__collector_popen(cmd=%s) interposing: line_mode=%d combo=%d\n", 1654 cmd ? cmd : "NULL", line_mode, get_combo_flag ()); 1655 int *guard = NULL; 1656 if (line_mode == LM_TRACK_LINEAGE) 1657 INIT_REENTRANCE (guard); 1658 if (guard == NULL) 1659 { 1660 #if ARCH(Intel) && WSIZE(32) 1661 return (real_popen) (cmd, mode); 1662 #else 1663 return CALL_REALF (popen)(cmd, mode); 1664 #endif 1665 } 1666 int following_combo = 0; 1667 linetrace_ext_combo_prologue ("popen", cmd, &following_combo); 1668 PUSH_REENTRANCE (guard); 1669 #if ARCH(Intel) && WSIZE(32) 1670 ret = (real_popen) (cmd, mode); 1671 #else 1672 ret = CALL_REALF (popen)(cmd, mode); 1673 #endif 1674 POP_REENTRANCE (guard); 1675 linetrace_ext_combo_epilogue ("popen", (ret == NULL) ? (-1) : 0, &following_combo); 1676 return ret; 1677 } 1678 1679 /*------------------------------------------------------------- grantpt */ 1680 int grantpt () __attribute__ ((weak, alias ("__collector_grantpt"))); 1681 1682 int 1683 __collector_grantpt (const int fildes) 1684 { 1685 if (NULL_PTR (grantpt)) 1686 init_lineage_intf (); 1687 TprintfT (DBG_LT0, 1688 "__collector_grantpt(%d) interposing: line_mode=%d combo=%d\n", 1689 fildes, line_mode, get_combo_flag ()); 1690 int *guard = NULL; 1691 if (line_mode == LM_TRACK_LINEAGE) 1692 INIT_REENTRANCE (guard); 1693 if (guard == NULL) 1694 return CALL_REAL (grantpt)(fildes); 1695 int following_combo = 0; 1696 linetrace_ext_combo_prologue ("grantpt", "/usr/lib/pt_chmod", &following_combo); 1697 PUSH_REENTRANCE (guard); 1698 int ret = CALL_REAL (grantpt)(fildes); 1699 POP_REENTRANCE (guard); 1700 linetrace_ext_combo_epilogue ("grantpt", ret, &following_combo); 1701 return ret; 1702 } 1703 1704 /*------------------------------------------------------------- ptsname */ 1705 char *ptsname () __attribute__ ((weak, alias ("__collector_ptsname"))); 1706 1707 char * 1708 __collector_ptsname (const int fildes) 1709 { 1710 if (NULL_PTR (ptsname)) 1711 init_lineage_intf (); 1712 TprintfT (DBG_LT0, 1713 "__collector_ptsname(%d) interposing: line_mode=%d combo=%d\n", 1714 fildes, line_mode, get_combo_flag ()); 1715 int *guard = NULL; 1716 if (line_mode == LM_TRACK_LINEAGE) 1717 INIT_REENTRANCE (guard); 1718 if (guard == NULL) 1719 return CALL_REALC (ptsname)(fildes); 1720 int following_combo = 0; 1721 linetrace_ext_combo_prologue ("ptsname", "/usr/lib/pt_chmod", &following_combo); 1722 PUSH_REENTRANCE (guard); 1723 char *ret = CALL_REALC (ptsname)(fildes); 1724 POP_REENTRANCE (guard); 1725 linetrace_ext_combo_epilogue ("ptsname", (ret == NULL) ? (-1) : 1, &following_combo); 1726 return ret; 1727 } 1728 1729 /*------------------------------------------------------------- clone */ 1730 /* clone can be fork-like or pthread_create-like, depending on whether 1731 * the flag CLONE_VM is set. If CLONE_VM is not set, then we interpose 1732 * clone in the way similar to interposing fork; if CLONE_VM is set, 1733 * then we interpose clone in the way similar to interposing pthread_create. 1734 * One special case is not handled: when CLONE_VM is set but CLONE_THREAD 1735 * is not, if the parent process exits earlier than the child process, 1736 * experiment will close, losing data from child process. 1737 */ 1738 typedef struct __collector_clone_arg 1739 { 1740 int (*fn)(void *); 1741 void * arg; 1742 char * new_lineage; 1743 int following_fork; 1744 } __collector_clone_arg_t; 1745 1746 static int 1747 __collector_clone_fn (void *fn_arg) 1748 { 1749 int (*fn)(void *) = ((__collector_clone_arg_t*) fn_arg)->fn; 1750 void * arg = ((__collector_clone_arg_t*) fn_arg)->arg; 1751 char * new_lineage = ((__collector_clone_arg_t*) fn_arg)->new_lineage; 1752 int following_fork = ((__collector_clone_arg_t*) fn_arg)->following_fork; 1753 __collector_freeCSize (__collector_heap, fn_arg, sizeof (__collector_clone_arg_t)); 1754 linetrace_ext_fork_epilogue ("clone", 0, new_lineage, &following_fork); 1755 return fn (arg); 1756 } 1757 1758 int clone (int (*fn)(void *), void *, int, void *, ...) __attribute__ ((weak, alias ("__collector_clone"))); 1759 1760 int 1761 __collector_clone (int (*fn)(void *), void *child_stack, int flags, void *arg, 1762 ... /* pid_t *ptid, struct user_desc *tls, pid_t *" ctid" */) 1763 { 1764 int ret; 1765 va_list va; 1766 if (flags & CLONE_VM) 1767 { 1768 va_start (va, arg); 1769 ret = __collector_ext_clone_pthread (fn, child_stack, flags, arg, va); 1770 va_end (va); 1771 } 1772 else 1773 { 1774 if (NULL_PTR (clone)) 1775 init_lineage_intf (); 1776 int *guard = NULL; 1777 int combo_flag = (line_mode == LM_TRACK_LINEAGE) ? ((CHCK_REENTRANCE (guard)) ? 1 : 0) : 0; 1778 TprintfT (DBG_LT0, "__collector_clone() interposition: line_mode=%d combo=%d\n", 1779 line_mode, combo_flag); 1780 char new_lineage[LT_MAXNAMELEN]; 1781 int following_fork = 0; 1782 __collector_clone_arg_t *funcinfo = __collector_allocCSize (__collector_heap, sizeof (__collector_clone_arg_t), 1); 1783 (*funcinfo).fn = fn; 1784 (*funcinfo).arg = arg; 1785 (*funcinfo).new_lineage = new_lineage; 1786 (*funcinfo).following_fork = 0; 1787 pid_t * ptid = NULL; 1788 struct user_desc * tls = NULL; 1789 pid_t * ctid = NULL; 1790 int num_args = 0; 1791 va_start (va, arg); 1792 if (flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) 1793 { 1794 ptid = va_arg (va, pid_t *); 1795 tls = va_arg (va, struct user_desc*); 1796 ctid = va_arg (va, pid_t *); 1797 num_args = 3; 1798 } 1799 else if (flags & CLONE_SETTLS) 1800 { 1801 ptid = va_arg (va, pid_t *); 1802 tls = va_arg (va, struct user_desc*); 1803 num_args = 2; 1804 } 1805 else if (flags & CLONE_PARENT_SETTID) 1806 { 1807 ptid = va_arg (va, pid_t *); 1808 num_args = 1; 1809 } 1810 if ((line_mode != LM_TRACK_LINEAGE) || combo_flag || funcinfo == NULL) 1811 { 1812 switch (num_args) 1813 { 1814 case 3: 1815 ret = CALL_REAL (clone)(fn, child_stack, flags, arg, ptid, tls, ctid); 1816 break; 1817 case 2: 1818 ret = CALL_REAL (clone)(fn, child_stack, flags, arg, ptid, tls); 1819 break; 1820 case 1: 1821 ret = CALL_REAL (clone)(fn, child_stack, flags, arg, ptid); 1822 break; 1823 default: 1824 ret = CALL_REAL (clone)(fn, child_stack, flags, arg); 1825 break; 1826 } 1827 1828 va_end (va); 1829 return ret; 1830 } 1831 linetrace_ext_fork_prologue ("clone", new_lineage, &following_fork); 1832 (*funcinfo).following_fork = following_fork; 1833 switch (num_args) 1834 { 1835 case 3: 1836 ret = CALL_REAL (clone)(__collector_clone_fn, child_stack, flags, funcinfo, ptid, tls, ctid); 1837 break; 1838 case 2: 1839 ret = CALL_REAL (clone)(__collector_clone_fn, child_stack, flags, funcinfo, ptid, tls); 1840 break; 1841 case 1: 1842 ret = CALL_REAL (clone)(__collector_clone_fn, child_stack, flags, funcinfo, ptid); 1843 break; 1844 default: 1845 ret = CALL_REAL (clone)(__collector_clone_fn, child_stack, flags, funcinfo); 1846 break; 1847 } 1848 va_end (va); 1849 if (ret < 0) 1850 __collector_freeCSize (__collector_heap, funcinfo, sizeof (__collector_clone_arg_t)); 1851 TprintfT (DBG_LT0, "__collector_clone() interposing: pid=%d\n", ret); 1852 linetrace_ext_fork_epilogue ("clone", ret, new_lineage, &following_fork); 1853 } 1854 return ret; 1855 } 1856 1857 /*-------------------------------------------------------------------- setuid */ 1858 int setuid () __attribute__ ((weak, alias ("__collector_setuid"))); 1859 int _setuid () __attribute__ ((weak, alias ("__collector_setuid"))); 1860 1861 int 1862 __collector_setuid (uid_t ruid) 1863 { 1864 if (NULL_PTR (setuid)) 1865 init_lineage_intf (); 1866 TprintfT (DBG_LT0, "__collector_setuid(0x%x) interposing\n", ruid); 1867 check_reuid_change (ruid, -1); 1868 int ret = CALL_REAL (setuid)(ruid); 1869 TprintfT (DBG_LT0, "__collector_setuid(0x%x) returning %d\n", ruid, ret); 1870 return ret; 1871 } 1872 1873 /*------------------------------------------------------------------- seteuid */ 1874 int seteuid () __attribute__ ((weak, alias ("__collector_seteuid"))); 1875 int _seteuid () __attribute__ ((weak, alias ("__collector_seteuid"))); 1876 1877 int 1878 __collector_seteuid (uid_t euid) 1879 { 1880 if (NULL_PTR (seteuid)) 1881 init_lineage_intf (); 1882 TprintfT (DBG_LT0, "__collector_seteuid(0x%x) interposing\n", euid); 1883 check_reuid_change (-1, euid); 1884 int ret = CALL_REAL (seteuid)(euid); 1885 TprintfT (DBG_LT0, "__collector_seteuid(0x%x) returning %d\n", euid, ret); 1886 return ret; 1887 } 1888 1889 /*------------------------------------------------------------------ setreuid */ 1890 int setreuid () __attribute__ ((weak, alias ("__collector_setreuid"))); 1891 int _setreuid () __attribute__ ((weak, alias ("__collector_setreuid"))); 1892 1893 int 1894 __collector_setreuid (uid_t ruid, uid_t euid) 1895 { 1896 if (NULL_PTR (setreuid)) 1897 init_lineage_intf (); 1898 TprintfT (DBG_LT0, "__collector_setreuid(0x%x,0x%x) interposing\n", ruid, euid); 1899 check_reuid_change (ruid, euid); 1900 int ret = CALL_REAL (setreuid)(ruid, euid); 1901 TprintfT (DBG_LT0, "__collector_setreuid(0x%x,0x%x) returning %d\n", ruid, euid, ret); 1902 return ret; 1903 } 1904 1905 /*-------------------------------------------------------------------- setgid */ 1906 int setgid () __attribute__ ((weak, alias ("__collector_setgid"))); 1907 int _setgid () __attribute__ ((weak, alias ("__collector_setgid"))); 1908 1909 int 1910 __collector_setgid (gid_t rgid) 1911 { 1912 if (NULL_PTR (setgid)) 1913 init_lineage_intf (); 1914 TprintfT (DBG_LT0, "__collector_setgid(0x%x) interposing\n", rgid); 1915 check_regid_change (rgid, -1); 1916 int ret = CALL_REAL (setgid)(rgid); 1917 TprintfT (DBG_LT0, "__collector_setgid(0x%x) returning %d\n", rgid, ret); 1918 return ret; 1919 } 1920 1921 /*------------------------------------------------------------------- setegid */ 1922 int setegid () __attribute__ ((weak, alias ("__collector_setegid"))); 1923 int _setegid () __attribute__ ((weak, alias ("__collector_setegid"))); 1924 1925 int 1926 __collector_setegid (gid_t egid) 1927 { 1928 if (NULL_PTR (setegid)) 1929 init_lineage_intf (); 1930 TprintfT (DBG_LT0, "__collector_setegid(0x%x) interposing\n", egid); 1931 check_regid_change (-1, egid); 1932 int ret = CALL_REAL (setegid)(egid); 1933 TprintfT (DBG_LT0, "__collector_setegid(0x%x) returning %d\n", egid, ret); 1934 return ret; 1935 } 1936 1937 /*------------------------------------------------------------------ setregid */ 1938 int setregid () __attribute__ ((weak, alias ("__collector_setregid"))); 1939 int _setregid () __attribute__ ((weak, alias ("__collector_setregid"))); 1940 1941 int 1942 __collector_setregid (gid_t rgid, gid_t egid) 1943 { 1944 if (NULL_PTR (setregid)) 1945 init_lineage_intf (); 1946 TprintfT (DBG_LT0, "__collector_setregid(0x%x,0x%x) interposing\n", rgid, egid); 1947 check_regid_change (rgid, egid); 1948 int ret = CALL_REAL (setregid)(rgid, egid); 1949 TprintfT (DBG_LT0, "__collector_setregid(0x%x,0x%x) returning %d\n", rgid, egid, ret); 1950 return ret; 1951 } 1952 1953 /*------------------------------------------------------- selective following */ 1954 1955 static int 1956 linetrace_follow_experiment (const char *follow_spec, const char *lineage_str, const char *progname) 1957 { 1958 regex_t regex_desc; 1959 if (!follow_spec) 1960 { 1961 TprintfT (DBG_LT0, "linetrace_follow_experiment(): MATCHES NULL follow_spec\n"); 1962 return 1; 1963 } 1964 int ercode = regcomp (®ex_desc, follow_spec, REG_EXTENDED | REG_NOSUB | REG_NEWLINE); 1965 if (ercode) 1966 { 1967 // syntax error in parsing string 1968 #ifdef DEBUG 1969 char errbuf[256]; 1970 regerror (ercode, ®ex_desc, errbuf, sizeof (errbuf)); 1971 TprintfT (DBG_LT0, "linetrace_follow_experiment: regerror()=%s\n", errbuf); 1972 #endif 1973 return 1; 1974 } 1975 TprintfT (DBG_LT0, "linetrace_follow_experiment(): compiled spec='%s'\n", follow_spec); 1976 if (lineage_str) 1977 { 1978 if (!regexec (®ex_desc, lineage_str, 0, NULL, 0)) 1979 { 1980 TprintfT (DBG_LT0, "linetrace_follow_experiment(): MATCHES lineage (follow_spec=%s,lineage=%s)\n", 1981 follow_spec, lineage_str); 1982 return 1; 1983 } 1984 } 1985 if (progname) 1986 { 1987 if (!regexec (®ex_desc, progname, 0, NULL, 0)) 1988 { 1989 TprintfT (DBG_LT0, "linetrace_follow_experiment(): MATCHES progname (follow_spec=%s,progname=%s)\n", 1990 follow_spec, progname); 1991 return 1; 1992 } 1993 } 1994 TprintfT (DBG_LT0, "linetrace_follow_experiment(): DOES NOT MATCH (follow_spec=%s,lineage=%s,progname=%s)\n", 1995 follow_spec, lineage_str ? lineage_str : "NULL", 1996 progname ? progname : "NULL"); 1997 return 0; 1998 } 1999