1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * This file contains a set of generic routines for periodically 31 * sampling the state of another process, or tree of processes. 32 * 33 * It is built upon the infrastructure provided by libproc. 34 */ 35 36 #include <sys/wait.h> 37 #include <sys/syscall.h> 38 #include <sys/time.h> 39 #include <libproc.h> 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <errno.h> 43 #include <unistd.h> 44 #include <signal.h> 45 #include <string.h> 46 #include <strings.h> 47 #include <limits.h> 48 #include <ctype.h> 49 #include <libintl.h> 50 #include <libcpc.h> 51 #include <sys/cpc_impl.h> 52 53 #include "libpctx.h" 54 55 struct __pctx { 56 pctx_errfn_t *errfn; 57 struct ps_prochandle *Pr; 58 void *uarg; 59 pctx_sysc_execfn_t *exec; 60 pctx_sysc_forkfn_t *fork; 61 pctx_sysc_exitfn_t *exit; 62 pctx_sysc_lwp_createfn_t *lwp_create; 63 pctx_init_lwpfn_t *init_lwp; 64 pctx_fini_lwpfn_t *fini_lwp; 65 pctx_sysc_lwp_exitfn_t *lwp_exit; 66 int verbose; 67 int created; 68 int sigblocked; 69 sigset_t savedset; 70 cpc_t *cpc; 71 }; 72 73 static void (*pctx_cpc_callback)(cpc_t *cpc, struct __pctx *pctx); 74 75 static void 76 pctx_default_errfn(const char *fn, const char *fmt, va_list ap) 77 { 78 (void) fprintf(stderr, "libpctx: pctx_%s: ", fn); 79 (void) vfprintf(stderr, fmt, ap); 80 } 81 82 /*PRINTFLIKE3*/ 83 static void 84 pctx_error(pctx_t *pctx, const char *fn, const char *fmt, ...) 85 { 86 va_list ap; 87 88 va_start(ap, fmt); 89 pctx->errfn(fn, fmt, ap); 90 va_end(ap); 91 } 92 93 /* 94 * Create a new process and bind the user args for it 95 */ 96 pctx_t * 97 pctx_create( 98 const char *filename, 99 char *const *argv, 100 void *arg, 101 int verbose, 102 pctx_errfn_t *errfn) 103 { 104 static const char fn[] = "create"; 105 int err; 106 pctx_t *pctx; 107 108 pctx = calloc(1, sizeof (*pctx)); 109 pctx->uarg = arg; 110 pctx->verbose = verbose; 111 pctx->errfn = errfn ? errfn : pctx_default_errfn; 112 113 if ((pctx->Pr = Pcreate(filename, argv, &err, 0, 0)) == NULL) { 114 switch (err) { 115 case C_PERM: 116 pctx_error(pctx, fn, gettext("cannot trace set-id or " 117 "unreadable program '%s'\n"), filename); 118 break; 119 case C_LP64: 120 pctx_error(pctx, fn, gettext("cannot control LP64 " 121 "program '%s'\n"), filename); 122 break; 123 case C_NOEXEC: 124 pctx_error(pctx, fn, gettext("cannot execute " 125 "program '%s'\n"), filename); 126 break; 127 case C_NOENT: 128 pctx_error(pctx, fn, gettext("cannot find" 129 "program '%s'\n"), filename); 130 break; 131 case C_FORK: 132 pctx_error(pctx, fn, gettext("cannot fork, " 133 "program '%s'\n"), filename); 134 break; 135 default: 136 pctx_error(pctx, fn, gettext("%s, program '%s'\n"), 137 Pcreate_error(err), filename); 138 break; 139 } 140 free(pctx); 141 return (NULL); 142 } 143 144 if (Psysentry(pctx->Pr, SYS_exit, 1) == -1) { 145 pctx_error(pctx, fn, 146 gettext("can't stop-on-exit() program '%s'\n"), filename); 147 Prelease(pctx->Pr, PRELEASE_KILL); 148 free(pctx); 149 return (NULL); 150 } 151 /* 152 * Set kill-on-last-close so the controlled process 153 * dies if we die. 154 */ 155 pctx->created = 1; 156 (void) Psetflags(pctx->Pr, PR_KLC); 157 (void) pctx_set_events(pctx, PCTX_NULL_EVENT); 158 159 return (pctx); 160 } 161 162 /* 163 * Capture an existing process and bind the user args for it 164 */ 165 pctx_t * 166 pctx_capture(pid_t pid, void *arg, int verbose, pctx_errfn_t *errfn) 167 { 168 static const char fn[] = "capture"; 169 int err; 170 pctx_t *pctx; 171 172 pctx = calloc(1, sizeof (*pctx)); 173 pctx->uarg = arg; 174 pctx->verbose = verbose; 175 pctx->errfn = errfn ? errfn : pctx_default_errfn; 176 177 if ((pctx->Pr = Pgrab(pid, 0, &err)) == NULL) { 178 switch (err) { 179 case G_NOPROC: 180 pctx_error(pctx, fn, 181 gettext("pid %d doesn't exist\n"), (int)pid); 182 break; 183 case G_ZOMB: 184 pctx_error(pctx, fn, 185 gettext("pid %d is a zombie\n"), (int)pid); 186 break; 187 case G_PERM: 188 pctx_error(pctx, fn, 189 gettext("pid %d: permission denied\n"), (int)pid); 190 break; 191 case G_BUSY: 192 pctx_error(pctx, fn, 193 gettext("pid %d is already being traced\n"), 194 (int)pid); 195 break; 196 case G_SYS: 197 pctx_error(pctx, fn, 198 gettext("pid %d is a system process\n"), (int)pid); 199 break; 200 case G_SELF: 201 pctx_error(pctx, fn, 202 gettext("cannot capture self!\n")); 203 break; 204 case G_LP64: 205 pctx_error(pctx, fn, gettext("cannot control LP64 " 206 "process, pid %d\n"), (int)pid); 207 break; 208 default: 209 pctx_error(pctx, fn, gettext("%s: pid %d\n"), 210 Pgrab_error(err), (int)pid); 211 break; 212 } 213 free(pctx); 214 return (NULL); 215 } 216 217 if (Psysentry(pctx->Pr, SYS_exit, 1) == -1) { 218 pctx_error(pctx, fn, 219 gettext("can't stop-on-exit() pid %d\n"), (int)pid); 220 Prelease(pctx->Pr, PRELEASE_CLEAR); 221 free(pctx); 222 return (NULL); 223 } 224 225 /* 226 * Set run-on-last-close so the controlled process 227 * runs even if we die on a signal. This is because 228 * we grabbed an existing process - it would be impolite 229 * to cause it to die if we exit prematurely. 230 */ 231 pctx->created = 0; 232 (void) Psetflags(pctx->Pr, PR_RLC); 233 (void) pctx_set_events(pctx, PCTX_NULL_EVENT); 234 235 return (pctx); 236 } 237 238 /*ARGSUSED*/ 239 static void 240 default_void(pctx_t *pctx) 241 {} 242 243 /*ARGSUSED*/ 244 static int 245 default_int(pctx_t *pctx) 246 { 247 return (0); 248 } 249 250 int 251 pctx_set_events(pctx_t *pctx, ...) 252 { 253 static const char fn[] = "set_events"; 254 va_list pvar; 255 int error = 0; 256 pctx_event_t event; 257 258 va_start(pvar, pctx); 259 do { 260 switch (event = (pctx_event_t)va_arg(pvar, pctx_event_t)) { 261 case PCTX_NULL_EVENT: 262 break; 263 case PCTX_SYSC_EXEC_EVENT: 264 pctx->exec = (pctx_sysc_execfn_t *) 265 va_arg(pvar, pctx_sysc_execfn_t *); 266 break; 267 case PCTX_SYSC_FORK_EVENT: 268 pctx->fork = (pctx_sysc_forkfn_t *) 269 va_arg(pvar, pctx_sysc_forkfn_t *); 270 break; 271 case PCTX_SYSC_EXIT_EVENT: /* always intercepted */ 272 pctx->exit = (pctx_sysc_exitfn_t *) 273 va_arg(pvar, pctx_sysc_exitfn_t *); 274 break; 275 case PCTX_SYSC_LWP_CREATE_EVENT: 276 pctx->lwp_create = (pctx_sysc_lwp_createfn_t *) 277 va_arg(pvar, pctx_sysc_lwp_createfn_t *); 278 break; 279 case PCTX_INIT_LWP_EVENT: 280 pctx->init_lwp = (pctx_init_lwpfn_t *) 281 va_arg(pvar, pctx_init_lwpfn_t *); 282 break; 283 case PCTX_FINI_LWP_EVENT: 284 pctx->fini_lwp = (pctx_fini_lwpfn_t *) 285 va_arg(pvar, pctx_fini_lwpfn_t *); 286 break; 287 case PCTX_SYSC_LWP_EXIT_EVENT: 288 pctx->lwp_exit = (pctx_sysc_lwp_exitfn_t *) 289 va_arg(pvar, pctx_sysc_lwp_exitfn_t *); 290 break; 291 default: 292 pctx_error(pctx, fn, 293 gettext("unknown event type %x\n"), event); 294 error = -1; 295 break; 296 } 297 } while (event != PCTX_NULL_EVENT && error == 0); 298 va_end(pvar); 299 300 if (error != 0) 301 return (error); 302 303 if (pctx->exec == NULL) 304 pctx->exec = (pctx_sysc_execfn_t *)default_int; 305 if (pctx->fork == NULL) 306 pctx->fork = (pctx_sysc_forkfn_t *)default_void; 307 if (pctx->exit == NULL) 308 pctx->exit = (pctx_sysc_exitfn_t *)default_void; 309 if (pctx->lwp_create == NULL) 310 pctx->lwp_create = (pctx_sysc_lwp_createfn_t *)default_int; 311 if (pctx->init_lwp == NULL) 312 pctx->init_lwp = (pctx_init_lwpfn_t *)default_int; 313 if (pctx->fini_lwp == NULL) 314 pctx->fini_lwp = (pctx_fini_lwpfn_t *)default_int; 315 if (pctx->lwp_exit == NULL) 316 pctx->lwp_exit = (pctx_sysc_lwp_exitfn_t *)default_int; 317 318 if (pctx->fork != (pctx_sysc_forkfn_t *)default_void) { 319 (void) Psysexit(pctx->Pr, SYS_forkall, 1); 320 (void) Psysexit(pctx->Pr, SYS_vfork, 1); 321 (void) Psysexit(pctx->Pr, SYS_fork1, 1); 322 (void) Psysexit(pctx->Pr, SYS_forksys, 1); 323 if (Psetflags(pctx->Pr, PR_FORK) == -1) 324 error = -1; 325 } else { 326 (void) Psysexit(pctx->Pr, SYS_forkall, 0); 327 (void) Psysexit(pctx->Pr, SYS_vfork, 0); 328 (void) Psysexit(pctx->Pr, SYS_fork1, 0); 329 (void) Psysexit(pctx->Pr, SYS_forksys, 0); 330 if (Punsetflags(pctx->Pr, PR_FORK) == -1) 331 error = -1; 332 } 333 334 /* 335 * exec causes termination of all but the exec-ing lwp, 336 * and resets the lwpid to one in the new address space. 337 */ 338 if (pctx->exec != (pctx_sysc_execfn_t *)default_int || 339 pctx->fini_lwp != (pctx_fini_lwpfn_t *)default_int || 340 pctx->init_lwp != (pctx_init_lwpfn_t *)default_int) { 341 (void) Psysexit(pctx->Pr, SYS_exec, 1); 342 (void) Psysexit(pctx->Pr, SYS_execve, 1); 343 (void) Psysentry(pctx->Pr, SYS_exec, 1); 344 (void) Psysentry(pctx->Pr, SYS_execve, 1); 345 } else { 346 (void) Psysexit(pctx->Pr, SYS_exec, 0); 347 (void) Psysexit(pctx->Pr, SYS_execve, 0); 348 (void) Psysentry(pctx->Pr, SYS_exec, 0); 349 (void) Psysentry(pctx->Pr, SYS_execve, 0); 350 } 351 352 (void) Psysexit(pctx->Pr, SYS_lwp_create, 353 pctx->lwp_create != (pctx_sysc_lwp_createfn_t *)default_int || 354 pctx->init_lwp != (pctx_init_lwpfn_t *)default_int); 355 356 (void) Psysentry(pctx->Pr, SYS_lwp_exit, 357 pctx->lwp_exit != (pctx_sysc_lwp_exitfn_t *)default_int || 358 pctx->fini_lwp != (pctx_fini_lwpfn_t *)default_int); 359 360 return (0); 361 } 362 363 static sigset_t termsig; 364 365 static void 366 __libpctx_init(void) 367 { 368 /* 369 * Initialize the signal set used to shield ourselves from 370 * death-by-terminal-signal while the agent lwp is running. 371 */ 372 (void) sigemptyset(&termsig); 373 (void) sigaddset(&termsig, SIGHUP); 374 (void) sigaddset(&termsig, SIGTERM); 375 (void) sigaddset(&termsig, SIGINT); 376 (void) sigaddset(&termsig, SIGQUIT); 377 } 378 379 #pragma init(__libpctx_init) 380 381 static void 382 pctx_begin_syscalls(pctx_t *pctx) 383 { 384 if (pctx->Pr == NULL) 385 return; 386 if (pctx->sigblocked++ == 0) { 387 (void) sigprocmask(SIG_BLOCK, &termsig, &pctx->savedset); 388 (void) Pcreate_agent(pctx->Pr); 389 } 390 } 391 392 static void 393 pctx_end_syscalls(pctx_t *pctx) 394 { 395 if (pctx->Pr == NULL) 396 return; 397 if (--pctx->sigblocked == 0) { 398 (void) Pdestroy_agent(pctx->Pr); 399 (void) sigprocmask(SIG_SETMASK, &pctx->savedset, NULL); 400 } 401 } 402 403 /* 404 * Iterate over the valid lwpids in the process, invoking the 405 * action function on each one. 406 */ 407 static int 408 pctx_lwpiterate(pctx_t *pctx, int (*action)(pctx_t *, pid_t, id_t, void *)) 409 { 410 const pstatus_t *pstatus; 411 char lstatus[64]; 412 struct stat statb; 413 lwpstatus_t *lwps; 414 prheader_t *prh; 415 int fd, nlwp; 416 int ret = 0; 417 418 if (action == (int (*)(pctx_t *, pid_t, id_t, void *))default_int) 419 return (0); 420 421 pstatus = Pstatus(pctx->Pr); 422 if (pstatus->pr_nlwp <= 1) { 423 pctx_begin_syscalls(pctx); 424 ret = action(pctx, pstatus->pr_pid, 1, pctx->uarg); 425 pctx_end_syscalls(pctx); 426 return (ret); 427 } 428 429 (void) snprintf(lstatus, sizeof (lstatus), 430 "/proc/%d/lstatus", (int)pstatus->pr_pid); 431 432 if ((fd = open(lstatus, O_RDONLY)) < 0 || 433 fstat(fd, &statb) != 0) { 434 if (fd >= 0) 435 (void) close(fd); 436 return (-1); 437 } 438 439 prh = malloc(statb.st_size); 440 if (read(fd, prh, statb.st_size) < 441 sizeof (prheader_t) + sizeof (lwpstatus_t)) { 442 (void) close(fd); 443 free(prh); 444 return (-1); 445 } 446 (void) close(fd); 447 448 /* LINTED pointer cast may result in improper alignment */ 449 lwps = (lwpstatus_t *)(prh + 1); 450 pctx_begin_syscalls(pctx); 451 for (nlwp = prh->pr_nent; nlwp > 0; nlwp--) { 452 if (action(pctx, 453 pstatus->pr_pid, lwps->pr_lwpid, pctx->uarg) != 0) 454 ret = -1; 455 /* LINTED pointer cast may result in improper alignment */ 456 lwps = (lwpstatus_t *)((char *)lwps + prh->pr_entsize); 457 } 458 pctx_end_syscalls(pctx); 459 free(prh); 460 return (ret); 461 } 462 463 /* 464 * Free any associated state, but leave the process stopped if it 465 * is still under our control. (If it isn't under our control, 466 * it should just run to completion when we do our last close) 467 */ 468 static void 469 pctx_free(pctx_t *pctx) 470 { 471 if (pctx->cpc != NULL && pctx_cpc_callback != NULL) 472 (*pctx_cpc_callback)(pctx->cpc, pctx); 473 if (pctx->Pr) { 474 Pfree(pctx->Pr); 475 pctx->Pr = NULL; 476 } 477 pctx->errfn = pctx_default_errfn; 478 } 479 480 /* 481 * Completely release the process from our control and discard all our state 482 */ 483 void 484 pctx_release(pctx_t *pctx) 485 { 486 if (pctx->Pr) { 487 Prelease(pctx->Pr, PRELEASE_CLEAR); 488 pctx->Pr = NULL; 489 } 490 pctx_free(pctx); 491 bzero(pctx, sizeof (*pctx)); 492 free(pctx); 493 } 494 495 static void 496 msincr(struct timeval *tv, uint_t msec) 497 { 498 tv->tv_sec += msec / MILLISEC; 499 tv->tv_usec += (msec % MILLISEC) * MILLISEC; 500 if (tv->tv_usec > MICROSEC) { 501 tv->tv_sec++; 502 tv->tv_usec -= MICROSEC; 503 } 504 } 505 506 static uint_t 507 msdiff(struct timeval *tva, struct timeval *tvb) 508 { 509 time_t sdiff = tva->tv_sec - tvb->tv_sec; 510 suseconds_t udiff = tva->tv_usec - tvb->tv_usec; 511 512 if (sdiff < 0) 513 return (0); 514 if (udiff < 0) { 515 udiff += MICROSEC; 516 sdiff--; 517 } 518 if (sdiff < 0) 519 return (0); 520 if (sdiff >= (INT_MAX / MILLISEC)) 521 return ((uint_t)INT_MAX); 522 return ((uint_t)(sdiff * MILLISEC + udiff / MILLISEC)); 523 } 524 525 int 526 pctx_run( 527 pctx_t *pctx, 528 uint_t msec, 529 uint_t nsamples, 530 int (*tick)(pctx_t *, pid_t, id_t, void *)) 531 { 532 static const char fn[] = "run"; 533 struct timeval tvgoal, tvnow; 534 uint_t mswait = 0; 535 int running = 1; 536 const pstatus_t *pstatus; 537 psinfo_t psinfo; 538 void (*sigsaved)(); 539 id_t lwpid; 540 pid_t pid = Pstatus(pctx->Pr)->pr_pid; 541 int pstate; 542 543 if (msec == 0) 544 nsamples = 0; 545 if (nsamples == 0) 546 nsamples = UINT_MAX; 547 548 /* 549 * Casually discard any knowledge of the children we create 550 */ 551 sigsaved = signal(SIGCHLD, SIG_IGN); 552 553 /* 554 * Since we've just "discovered" this process which might have 555 * been running for weeks, deliver some init_lwp events so 556 * that our caller gets a handle on the process. 557 */ 558 if (pctx_lwpiterate(pctx, pctx->init_lwp) != 0) { 559 if (pctx->verbose) 560 pctx_error(pctx, fn, 561 gettext("%d: lwp discovery failed\n"), (int)pid); 562 goto bailout; 563 } 564 565 if (msec != 0) { 566 /* 567 * tvgoal represents the time at which the sample 568 * should next be taken. 569 */ 570 (void) gettimeofday(&tvgoal, 0); 571 msincr(&tvgoal, msec); 572 } 573 574 /* 575 * The event handling loop continues while running is 1. 576 * running becomes 0 when either the controlled process has 577 * exited successfully or the number of time samples has expired. 578 * Otherwise, if an error has occurred, running becomes -1. 579 */ 580 while (running == 1) { 581 582 if (Psetrun(pctx->Pr, 0, 0) != 0) { 583 if (pctx->verbose) 584 pctx_error(pctx, fn, 585 gettext("%d: Psetrun\n"), (int)pid); 586 break; 587 } 588 589 if (msec != 0) { 590 /* 591 * This timing loop attempts to estimate the number 592 * of milliseconds between our "goal" time (when 593 * we should stop the process and run the tick 594 * routine) and the current time. 595 * 596 * If we ever find ourselves running behind i.e. we 597 * missed our goal, then we skip ahead to the next 598 * goal instead. 599 */ 600 do { 601 (void) gettimeofday(&tvnow, 0); 602 if ((mswait = msdiff(&tvgoal, &tvnow)) == 0) { 603 msincr(&tvgoal, msec); 604 /* 605 * Skip ahead to the next goal, unless 606 * there is only one more sample left 607 * to take. 608 */ 609 if (nsamples != 1) 610 nsamples--; 611 } 612 } while (mswait == 0); 613 } 614 615 (void) Pwait(pctx->Pr, mswait); 616 617 checkstate: 618 switch (pstate = Pstate(pctx->Pr)) { 619 case PS_RUN: 620 /* 621 * Try again, but wait for up to 5 seconds. 622 */ 623 if (Pstop(pctx->Pr, 5 * MILLISEC) == -1 || 624 (pstate = Pstate(pctx->Pr)) != PS_STOP) { 625 pctx_error(pctx, fn, 626 gettext("%d: won't stop\n"), (int)pid); 627 } 628 break; 629 case PS_STOP: 630 break; 631 case PS_LOST: 632 /* 633 * Lost control - probably execed a setuid/setgid 634 * executable. Try and get control back again, 635 * else bail .. 636 */ 637 (void) Preopen(pctx->Pr); 638 if ((pstate = Pstate(pctx->Pr)) != PS_LOST) 639 goto checkstate; 640 pctx_error(pctx, fn, 641 gettext("%d: execed a program that cannot " 642 "be tracked\n"), (int)pid); 643 running = -1; 644 break; 645 case PS_UNDEAD: 646 case PS_DEAD: 647 if (pctx->verbose) 648 pctx_error(pctx, fn, 649 gettext("%d: process terminated\n"), 650 (int)pid); 651 running = -1; 652 break; 653 default: 654 if (pctx->verbose) 655 pctx_error(pctx, fn, 656 gettext("%d: process state 0x%x?\n"), 657 (int)pid, pstate); 658 break; 659 } 660 661 if (pstate != PS_STOP) 662 break; 663 664 pstatus = Pstatus(pctx->Pr); 665 lwpid = pstatus->pr_lwp.pr_lwpid; 666 switch (pstatus->pr_lwp.pr_why) { 667 case PR_REQUESTED: 668 msincr(&tvgoal, msec); 669 if (pstatus->pr_flags & PR_VFORKP) { 670 /* 671 * The process is in a vfork stupor until 672 * its child releases it via an exec. 673 * Don't sample it while it's in this state 674 * - we won't be able to create the agent. 675 */ 676 break; 677 } 678 if (pctx_lwpiterate(pctx, tick) != 0) 679 running = -1; 680 if (running == 1 && --nsamples == 0) 681 running = 0; 682 break; 683 case PR_SYSENTRY: 684 switch (pstatus->pr_lwp.pr_what) { 685 case SYS_lwp_exit: 686 pctx_begin_syscalls(pctx); 687 (void) pctx->fini_lwp(pctx, 688 pid, lwpid, pctx->uarg); 689 (void) pctx->lwp_exit(pctx, 690 pid, lwpid, pctx->uarg); 691 pctx_end_syscalls(pctx); 692 break; 693 case SYS_exit: 694 if (pctx_lwpiterate(pctx, pctx->fini_lwp) 695 != 0) 696 running = -1; 697 pctx->exit(pctx, pid, lwpid, 698 (int)pstatus->pr_lwp.pr_sysarg[0], 699 pctx->uarg); 700 if (running == 1) 701 running = 0; 702 break; 703 case SYS_exec: 704 case SYS_execve: 705 (void) pctx_lwpiterate(pctx, pctx->fini_lwp); 706 break; 707 default: 708 pctx_error(pctx, fn, 709 "warning - pid %d sysentry(%d)\n", 710 (int)pid, pstatus->pr_lwp.pr_what); 711 break; 712 } 713 break; 714 case PR_SYSEXIT: 715 switch (pstatus->pr_lwp.pr_what) { 716 case SYS_exec: 717 case SYS_execve: 718 if (pstatus->pr_lwp.pr_errno) { 719 /* 720 * The exec failed completely. 721 * Reinstate the lwps we fini'd 722 * at exec entrance 723 */ 724 if (pctx_lwpiterate(pctx, 725 pctx->init_lwp) == 0) 726 running = 1; 727 else 728 running = -1; 729 break; 730 } 731 if (pctx->exec == (pctx_sysc_execfn_t *) 732 default_int) { 733 running = 0; 734 break; 735 } 736 (void) memcpy(&psinfo, 737 Ppsinfo(pctx->Pr), sizeof (psinfo)); 738 proc_unctrl_psinfo(&psinfo); 739 pctx_begin_syscalls(pctx); 740 if (pctx->exec(pctx, pid, lwpid, 741 psinfo.pr_psargs, pctx->uarg) != 0) 742 running = -1; 743 if (running == 1 && pctx->init_lwp(pctx, 744 pid, 1, pctx->uarg) != 0) 745 running = -1; 746 pctx_end_syscalls(pctx); 747 break; 748 case SYS_lwp_create: 749 if (pstatus->pr_lwp.pr_errno || 750 pstatus->pr_lwp.pr_rval1) 751 break; 752 pctx_begin_syscalls(pctx); 753 if (pctx->init_lwp(pctx, pid, lwpid, 754 pctx->uarg) != 0) 755 running = -1; 756 if (running == 1 && pctx->lwp_create(pctx, 757 pid, lwpid, pctx->uarg) != 0) 758 running = -1; 759 pctx_end_syscalls(pctx); 760 break; 761 case SYS_forkall: 762 case SYS_vfork: 763 case SYS_fork1: 764 case SYS_forksys: 765 if (pstatus->pr_lwp.pr_errno) 766 break; 767 (void) fflush(NULL); 768 switch (fork1()) { 769 pid_t ppid; 770 int wascreated; 771 pctx_sysc_forkfn_t *forkfn; 772 case 0: 773 ppid = pid; 774 pid = pstatus->pr_lwp.pr_rval1; 775 wascreated = pctx->created; 776 forkfn = pctx->fork; 777 pctx_free(pctx); 778 pctx = pctx_capture(pid, pctx->uarg, 779 pctx->verbose, pctx->errfn); 780 if (pctx != NULL) { 781 if (wascreated) { 782 /* 783 * Set kill on last 784 * close so -all- 785 * children die. 786 */ 787 pctx->created = 1; 788 (void) Psetflags( 789 pctx->Pr, PR_KLC); 790 } 791 (*forkfn)(pctx, ppid, pid, 792 lwpid, pctx->uarg); 793 pctx_release(pctx); 794 _exit(0); 795 } else { 796 _exit(1); 797 } 798 /*NOTREACHED*/ 799 case -1: 800 pctx_error(pctx, fn, 801 "cannot follow pid %d: %s\n", 802 (int)pstatus->pr_lwp.pr_rval1, 803 strerror(errno)); 804 break; 805 default: 806 break; 807 } 808 break; 809 default: 810 pctx_error(pctx, fn, gettext( 811 "warning - pid %d sysexit(%d)\n"), 812 (int)pid, pstatus->pr_lwp.pr_what); 813 break; 814 } 815 break; 816 case PR_SIGNALLED: 817 if (pctx->verbose) 818 pctx_error(pctx, fn, 819 gettext("pid %d - signalled\n"), (int)pid); 820 break; 821 case PR_JOBCONTROL: 822 if (pctx->verbose) 823 pctx_error(pctx, fn, 824 gettext("pid %d - job control stop\n"), 825 (int)pid); 826 running = -1; 827 break; 828 case PR_FAULTED: 829 if (pctx->verbose) 830 pctx_error(pctx, fn, 831 gettext("pid %d - faulted\n"), (int)pid); 832 break; 833 case PR_SUSPENDED: 834 if (pctx->verbose) 835 pctx_error(pctx, fn, 836 gettext("pid %d - suspended\n"), (int)pid); 837 break; 838 case PR_CHECKPOINT: 839 if (pctx->verbose) 840 pctx_error(pctx, fn, 841 gettext("pid %d - checkpoint\n"), 842 (int)pid); 843 break; 844 default: 845 if (pctx->verbose) 846 pctx_error(pctx, fn, 847 gettext("pid %d - reason %d\n"), 848 (int)pid, pstatus->pr_lwp.pr_why); 849 running = -1; 850 break; 851 } 852 } 853 854 bailout: 855 (void) signal(SIGCHLD, sigsaved); 856 857 switch (running) { 858 case 0: 859 return (0); 860 case -1: 861 return (-1); 862 default: 863 pctx_error(pctx, fn, gettext("lost control of pid %d\n"), 864 (int)pid); 865 pctx_free(pctx); 866 return (-1); 867 } 868 } 869 870 /* 871 * Execute the private 'cpc' system call in the context of the 872 * controlled process. 873 */ 874 int 875 __pctx_cpc(pctx_t *pctx, cpc_t *cpc, 876 int cmd, id_t lwpid, void *data1, void *data2, void *data3, int bufsize) 877 { 878 sysret_t rval; 879 argdes_t argd[5]; 880 argdes_t *adp = &argd[0]; 881 int error; 882 883 /* 884 * Keep track of the relationship between cpc_t and pctx_t here. 885 * We store the last cpc_t used by libpctx, so that when this pctx is 886 * destroyed, libpctx can notify libcpc. 887 */ 888 if (pctx->cpc != NULL && pctx->cpc != cpc && pctx_cpc_callback != NULL) 889 (*pctx_cpc_callback)(pctx->cpc, pctx); 890 pctx->cpc = cpc; 891 892 /* 893 * cmd and lwpid are passed in by value no matter what the command is. 894 */ 895 adp->arg_value = cmd; 896 adp->arg_object = NULL; 897 adp->arg_type = AT_BYVAL; 898 adp->arg_inout = AI_INPUT; 899 adp->arg_size = 0; 900 adp++; 901 902 adp->arg_value = lwpid; 903 adp->arg_object = NULL; 904 adp->arg_type = AT_BYVAL; 905 adp->arg_inout = AI_INPUT; 906 adp->arg_size = 0; 907 adp++; 908 909 switch (cmd) { 910 case CPC_BIND: 911 adp->arg_value = 0; 912 adp->arg_object = data1; 913 adp->arg_type = AT_BYREF; 914 adp->arg_inout = AI_INPUT; 915 adp->arg_size = (size_t)data2; 916 adp++; 917 918 adp->arg_value = (size_t)data2; 919 adp->arg_object = NULL; 920 adp->arg_type = AT_BYVAL; 921 adp->arg_inout = AI_INPUT; 922 adp->arg_size = 0; 923 adp++; 924 925 adp->arg_value = 0; 926 adp->arg_object = data3; 927 adp->arg_type = AT_BYREF; 928 adp->arg_inout = AI_INOUT; 929 adp->arg_size = sizeof (int); 930 931 break; 932 case CPC_SAMPLE: 933 adp->arg_value = 0; 934 adp->arg_object = data1; 935 adp->arg_type = AT_BYREF; 936 adp->arg_inout = AI_OUTPUT; 937 adp->arg_size = bufsize; 938 adp++; 939 940 adp->arg_value = 0; 941 adp->arg_object = data2; 942 adp->arg_type = AT_BYREF; 943 adp->arg_inout = AI_OUTPUT; 944 adp->arg_size = sizeof (hrtime_t); 945 adp++; 946 947 adp->arg_value = 0; 948 adp->arg_object = data3; 949 adp->arg_type = AT_BYREF; 950 adp->arg_inout = AI_OUTPUT; 951 adp->arg_size = sizeof (uint64_t); 952 953 break; 954 default: 955 adp->arg_value = 0; 956 adp->arg_object = 0; 957 adp->arg_type = AT_BYVAL; 958 adp->arg_inout = AI_INPUT; 959 adp->arg_size = 0; 960 adp++; 961 962 adp->arg_value = 0; 963 adp->arg_object = 0; 964 adp->arg_type = AT_BYVAL; 965 adp->arg_inout = AI_INPUT; 966 adp->arg_size = 0; 967 adp++; 968 969 adp->arg_value = 0; 970 adp->arg_object = 0; 971 adp->arg_type = AT_BYVAL; 972 adp->arg_inout = AI_INPUT; 973 adp->arg_size = 0; 974 975 break; 976 } 977 978 error = Psyscall(pctx->Pr, &rval, SYS_cpc, 5, &argd[0]); 979 980 if (error) { 981 errno = error > 0 ? error : ENOSYS; 982 return (-1); 983 } 984 return (rval.sys_rval1); 985 } 986 987 /* 988 * libcpc-private hook used to register a callback. The callback is used to 989 * notify libcpc when a pctx handle is invalidated. 990 */ 991 void 992 __pctx_cpc_register_callback(void (*arg)(struct __cpc *, struct __pctx *)) 993 { 994 pctx_cpc_callback = arg; 995 } 996