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 2010 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /*
28 * This file contains a set of generic routines for periodically
29 * sampling the state of another process, or tree of processes.
30 *
31 * It is built upon the infrastructure provided by libproc.
32 */
33
34 #include <sys/wait.h>
35 #include <sys/syscall.h>
36 #include <sys/time.h>
37 #include <libproc.h>
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <errno.h>
41 #include <unistd.h>
42 #include <signal.h>
43 #include <string.h>
44 #include <strings.h>
45 #include <limits.h>
46 #include <ctype.h>
47 #include <libintl.h>
48 #include <libcpc.h>
49 #include <sys/cpc_impl.h>
50
51 #include "libpctx.h"
52
53 struct __pctx {
54 pctx_errfn_t *errfn;
55 struct ps_prochandle *Pr;
56 void *uarg;
57 pctx_sysc_execfn_t *exec;
58 pctx_sysc_forkfn_t *fork;
59 pctx_sysc_exitfn_t *exit;
60 pctx_sysc_lwp_createfn_t *lwp_create;
61 pctx_init_lwpfn_t *init_lwp;
62 pctx_fini_lwpfn_t *fini_lwp;
63 pctx_sysc_lwp_exitfn_t *lwp_exit;
64 int verbose;
65 int created;
66 int sigblocked;
67 int terminate;
68 sigset_t savedset;
69 cpc_t *cpc;
70 };
71
72 static void (*pctx_cpc_callback)(cpc_t *cpc, struct __pctx *pctx);
73
74 static void
pctx_default_errfn(const char * fn,const char * fmt,va_list ap)75 pctx_default_errfn(const char *fn, const char *fmt, va_list ap)
76 {
77 (void) fprintf(stderr, "libpctx: pctx_%s: ", fn);
78 (void) vfprintf(stderr, fmt, ap);
79 }
80
81 /*PRINTFLIKE3*/
82 static void
pctx_error(pctx_t * pctx,const char * fn,const char * fmt,...)83 pctx_error(pctx_t *pctx, const char *fn, const char *fmt, ...)
84 {
85 va_list ap;
86
87 va_start(ap, fmt);
88 pctx->errfn(fn, fmt, ap);
89 va_end(ap);
90 }
91
92 /*
93 * Create a new process and bind the user args for it
94 */
95 pctx_t *
pctx_create(const char * filename,char * const * argv,void * arg,int verbose,pctx_errfn_t * errfn)96 pctx_create(
97 const char *filename,
98 char *const *argv,
99 void *arg,
100 int verbose,
101 pctx_errfn_t *errfn)
102 {
103 static const char fn[] = "create";
104 int err;
105 pctx_t *pctx;
106
107 pctx = calloc(1, sizeof (*pctx));
108 pctx->uarg = arg;
109 pctx->verbose = verbose;
110 pctx->terminate = 0;
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 *
pctx_capture(pid_t pid,void * arg,int verbose,pctx_errfn_t * errfn)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
default_void(pctx_t * pctx)240 default_void(pctx_t *pctx)
241 {}
242
243 /*ARGSUSED*/
244 static int
default_int(pctx_t * pctx)245 default_int(pctx_t *pctx)
246 {
247 return (0);
248 }
249
250 int
pctx_set_events(pctx_t * pctx,...)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 *)(uintptr_t)default_int;
305 if (pctx->fork == NULL)
306 pctx->fork = (pctx_sysc_forkfn_t *)(uintptr_t)default_void;
307 if (pctx->exit == NULL)
308 pctx->exit = (pctx_sysc_exitfn_t *)(uintptr_t)default_void;
309 if (pctx->lwp_create == NULL)
310 pctx->lwp_create = (pctx_sysc_lwp_createfn_t *)
311 (uintptr_t)default_int;
312 if (pctx->init_lwp == NULL)
313 pctx->init_lwp = (pctx_init_lwpfn_t *)(uintptr_t)default_int;
314 if (pctx->fini_lwp == NULL)
315 pctx->fini_lwp = (pctx_fini_lwpfn_t *)(uintptr_t)default_int;
316 if (pctx->lwp_exit == NULL)
317 pctx->lwp_exit = (pctx_sysc_lwp_exitfn_t *)
318 (uintptr_t)default_int;
319
320 if ((uintptr_t)pctx->fork != (uintptr_t)default_void) {
321 (void) Psysexit(pctx->Pr, SYS_vfork, 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_vfork, 0);
327 (void) Psysexit(pctx->Pr, SYS_forksys, 0);
328 if (Punsetflags(pctx->Pr, PR_FORK) == -1)
329 error = -1;
330 }
331
332 /*
333 * exec causes termination of all but the exec-ing lwp,
334 * and resets the lwpid to one in the new address space.
335 */
336 if ((uintptr_t)pctx->exec != (uintptr_t)default_int ||
337 (uintptr_t)pctx->fini_lwp != (uintptr_t)default_int ||
338 (uintptr_t)pctx->init_lwp != (uintptr_t)default_int) {
339 (void) Psysexit(pctx->Pr, SYS_execve, 1);
340 (void) Psysentry(pctx->Pr, SYS_execve, 1);
341 } else {
342 (void) Psysexit(pctx->Pr, SYS_execve, 0);
343 (void) Psysentry(pctx->Pr, SYS_execve, 0);
344 }
345
346 (void) Psysexit(pctx->Pr, SYS_lwp_create,
347 (uintptr_t)pctx->lwp_create != (uintptr_t)default_int ||
348 (uintptr_t)pctx->init_lwp != (uintptr_t)default_int);
349
350 (void) Psysentry(pctx->Pr, SYS_lwp_exit,
351 (uintptr_t)pctx->lwp_exit != (uintptr_t)default_int ||
352 (uintptr_t)pctx->fini_lwp != (uintptr_t)default_int);
353
354 return (0);
355 }
356
357 static sigset_t termsig;
358
359 static void
__libpctx_init(void)360 __libpctx_init(void)
361 {
362 /*
363 * Initialize the signal set used to shield ourselves from
364 * death-by-terminal-signal while the agent lwp is running.
365 */
366 (void) sigemptyset(&termsig);
367 (void) sigaddset(&termsig, SIGHUP);
368 (void) sigaddset(&termsig, SIGTERM);
369 (void) sigaddset(&termsig, SIGINT);
370 (void) sigaddset(&termsig, SIGQUIT);
371 }
372
373 #pragma init(__libpctx_init)
374
375 static void
pctx_begin_syscalls(pctx_t * pctx)376 pctx_begin_syscalls(pctx_t *pctx)
377 {
378 if (pctx->Pr == NULL)
379 return;
380 if (pctx->sigblocked++ == 0) {
381 (void) sigprocmask(SIG_BLOCK, &termsig, &pctx->savedset);
382 (void) Pcreate_agent(pctx->Pr);
383 }
384 }
385
386 static void
pctx_end_syscalls(pctx_t * pctx)387 pctx_end_syscalls(pctx_t *pctx)
388 {
389 if (pctx->Pr == NULL)
390 return;
391 if (--pctx->sigblocked == 0) {
392 (void) Pdestroy_agent(pctx->Pr);
393 (void) sigprocmask(SIG_SETMASK, &pctx->savedset, NULL);
394 }
395 }
396
397 /*
398 * Iterate over the valid lwpids in the process, invoking the
399 * action function on each one.
400 */
401 static int
pctx_lwpiterate(pctx_t * pctx,int (* action)(pctx_t *,pid_t,id_t,void *))402 pctx_lwpiterate(pctx_t *pctx, int (*action)(pctx_t *, pid_t, id_t, void *))
403 {
404 const pstatus_t *pstatus;
405 char lstatus[64];
406 struct stat statb;
407 lwpstatus_t *lwps;
408 prheader_t *prh;
409 int fd, nlwp;
410 int ret = 0;
411
412 if ((uintptr_t)action == (uintptr_t)default_int)
413 return (0);
414
415 pstatus = Pstatus(pctx->Pr);
416 if (pstatus->pr_nlwp <= 1) {
417 pctx_begin_syscalls(pctx);
418 ret = action(pctx, pstatus->pr_pid, 1, pctx->uarg);
419 pctx_end_syscalls(pctx);
420 return (ret);
421 }
422
423 (void) snprintf(lstatus, sizeof (lstatus),
424 "/proc/%d/lstatus", (int)pstatus->pr_pid);
425
426 if ((fd = open(lstatus, O_RDONLY)) < 0 ||
427 fstat(fd, &statb) != 0) {
428 if (fd >= 0)
429 (void) close(fd);
430 return (-1);
431 }
432
433 prh = malloc(statb.st_size);
434 if (read(fd, prh, statb.st_size) <
435 sizeof (prheader_t) + sizeof (lwpstatus_t)) {
436 (void) close(fd);
437 free(prh);
438 return (-1);
439 }
440 (void) close(fd);
441
442 /* LINTED pointer cast may result in improper alignment */
443 lwps = (lwpstatus_t *)(prh + 1);
444 pctx_begin_syscalls(pctx);
445 for (nlwp = prh->pr_nent; nlwp > 0; nlwp--) {
446 if (action(pctx,
447 pstatus->pr_pid, lwps->pr_lwpid, pctx->uarg) != 0)
448 ret = -1;
449 /* LINTED pointer cast may result in improper alignment */
450 lwps = (lwpstatus_t *)((char *)lwps + prh->pr_entsize);
451 }
452 pctx_end_syscalls(pctx);
453 free(prh);
454 return (ret);
455 }
456
457 /*
458 * Free any associated state, but leave the process stopped if it
459 * is still under our control. (If it isn't under our control,
460 * it should just run to completion when we do our last close)
461 */
462 static void
pctx_free(pctx_t * pctx)463 pctx_free(pctx_t *pctx)
464 {
465 if (pctx->cpc != NULL && pctx_cpc_callback != NULL)
466 (*pctx_cpc_callback)(pctx->cpc, pctx);
467 if (pctx->Pr) {
468 Pfree(pctx->Pr);
469 pctx->Pr = NULL;
470 }
471 pctx->errfn = pctx_default_errfn;
472 }
473
474 /*
475 * Completely release the process from our control and discard all our state
476 */
477 void
pctx_release(pctx_t * pctx)478 pctx_release(pctx_t *pctx)
479 {
480 if (pctx->Pr) {
481 Prelease(pctx->Pr, PRELEASE_CLEAR);
482 pctx->Pr = NULL;
483 }
484
485 pctx_free(pctx);
486 bzero(pctx, sizeof (*pctx));
487 free(pctx);
488 }
489
490 static void
msincr(struct timeval * tv,uint_t msec)491 msincr(struct timeval *tv, uint_t msec)
492 {
493 tv->tv_sec += msec / MILLISEC;
494 tv->tv_usec += (msec % MILLISEC) * MILLISEC;
495 if (tv->tv_usec > MICROSEC) {
496 tv->tv_sec++;
497 tv->tv_usec -= MICROSEC;
498 }
499 }
500
501 static uint_t
msdiff(struct timeval * tva,struct timeval * tvb)502 msdiff(struct timeval *tva, struct timeval *tvb)
503 {
504 time_t sdiff = tva->tv_sec - tvb->tv_sec;
505 suseconds_t udiff = tva->tv_usec - tvb->tv_usec;
506
507 if (sdiff < 0)
508 return (0);
509 if (udiff < 0) {
510 udiff += MICROSEC;
511 sdiff--;
512 }
513 if (sdiff < 0)
514 return (0);
515 if (sdiff >= (INT_MAX / MILLISEC))
516 return ((uint_t)INT_MAX);
517 return ((uint_t)(sdiff * MILLISEC + udiff / MILLISEC));
518 }
519
520 int
pctx_run(pctx_t * pctx,uint_t msec,uint_t nsamples,int (* tick)(pctx_t *,pid_t,id_t,void *))521 pctx_run(
522 pctx_t *pctx,
523 uint_t msec,
524 uint_t nsamples,
525 int (*tick)(pctx_t *, pid_t, id_t, void *))
526 {
527 static const char fn[] = "run";
528 struct timeval tvgoal, tvnow;
529 uint_t mswait = 0;
530 int running = 1;
531 const pstatus_t *pstatus;
532 psinfo_t psinfo;
533 void (*sigsaved)();
534 id_t lwpid;
535 pid_t pid = Pstatus(pctx->Pr)->pr_pid;
536 int pstate;
537
538 if (msec == 0)
539 nsamples = 0;
540 if (nsamples == 0)
541 nsamples = UINT_MAX;
542
543 /*
544 * Casually discard any knowledge of the children we create
545 */
546 sigsaved = signal(SIGCHLD, SIG_IGN);
547
548 /*
549 * Since we've just "discovered" this process which might have
550 * been running for weeks, deliver some init_lwp events so
551 * that our caller gets a handle on the process.
552 */
553 if (pctx_lwpiterate(pctx, pctx->init_lwp) != 0) {
554 if (pctx->verbose)
555 pctx_error(pctx, fn,
556 gettext("%d: lwp discovery failed\n"), (int)pid);
557 goto bailout;
558 }
559
560 if (msec != 0) {
561 /*
562 * tvgoal represents the time at which the sample
563 * should next be taken.
564 */
565 (void) gettimeofday(&tvgoal, 0);
566 msincr(&tvgoal, msec);
567 }
568
569 /*
570 * The event handling loop continues while running is 1.
571 * running becomes 0 when either the controlled process has
572 * exited successfully or the number of time samples has expired.
573 * Otherwise, if an error has occurred, running becomes -1.
574 */
575 while (running == 1 && !pctx->terminate) {
576
577 if (Psetrun(pctx->Pr, 0, 0) != 0) {
578 if (pctx->verbose)
579 pctx_error(pctx, fn,
580 gettext("%d: Psetrun\n"), (int)pid);
581 break;
582 }
583
584 if (msec != 0) {
585 /*
586 * This timing loop attempts to estimate the number
587 * of milliseconds between our "goal" time (when
588 * we should stop the process and run the tick
589 * routine) and the current time.
590 *
591 * If we ever find ourselves running behind i.e. we
592 * missed our goal, then we skip ahead to the next
593 * goal instead.
594 */
595 do {
596 (void) gettimeofday(&tvnow, 0);
597 if ((mswait = msdiff(&tvgoal, &tvnow)) == 0) {
598 msincr(&tvgoal, msec);
599 /*
600 * Skip ahead to the next goal, unless
601 * there is only one more sample left
602 * to take.
603 */
604 if (nsamples != 1)
605 nsamples--;
606 }
607 } while (mswait == 0 && !pctx->terminate);
608 }
609
610 if (pctx->terminate)
611 goto bailout;
612 else
613 (void) Pwait(pctx->Pr, mswait);
614
615 checkstate:
616 switch (pstate = Pstate(pctx->Pr)) {
617 case PS_RUN:
618 /*
619 * Try again, but wait for up to 5 seconds.
620 */
621 if (Pstop(pctx->Pr, 5 * MILLISEC) == -1 ||
622 (pstate = Pstate(pctx->Pr)) != PS_STOP) {
623 pctx_error(pctx, fn,
624 gettext("%d: won't stop\n"), (int)pid);
625 }
626 break;
627 case PS_STOP:
628 break;
629 case PS_LOST:
630 /*
631 * Lost control - probably execed a setuid/setgid
632 * executable. Try and get control back again,
633 * else bail ..
634 */
635 (void) Preopen(pctx->Pr);
636 if ((pstate = Pstate(pctx->Pr)) != PS_LOST)
637 goto checkstate;
638 pctx_error(pctx, fn,
639 gettext("%d: execed a program that cannot "
640 "be tracked\n"), (int)pid);
641 running = -1;
642 break;
643 case PS_UNDEAD:
644 case PS_DEAD:
645 if (pctx->verbose)
646 pctx_error(pctx, fn,
647 gettext("%d: process terminated\n"),
648 (int)pid);
649 running = -1;
650 break;
651 default:
652 if (pctx->verbose)
653 pctx_error(pctx, fn,
654 gettext("%d: process state 0x%x?\n"),
655 (int)pid, pstate);
656 break;
657 }
658
659 if (pstate != PS_STOP)
660 break;
661
662 pstatus = Pstatus(pctx->Pr);
663 lwpid = pstatus->pr_lwp.pr_lwpid;
664 switch (pstatus->pr_lwp.pr_why) {
665 case PR_REQUESTED:
666 msincr(&tvgoal, msec);
667 if (pstatus->pr_flags & PR_VFORKP) {
668 /*
669 * The process is in a vfork stupor until
670 * its child releases it via an exec.
671 * Don't sample it while it's in this state
672 * - we won't be able to create the agent.
673 */
674 break;
675 }
676 if (pctx_lwpiterate(pctx, tick) != 0)
677 running = -1;
678 if (running == 1 && --nsamples == 0)
679 running = 0;
680 break;
681 case PR_SYSENTRY:
682 switch (pstatus->pr_lwp.pr_what) {
683 case SYS_lwp_exit:
684 pctx_begin_syscalls(pctx);
685 (void) pctx->fini_lwp(pctx,
686 pid, lwpid, pctx->uarg);
687 (void) pctx->lwp_exit(pctx,
688 pid, lwpid, pctx->uarg);
689 pctx_end_syscalls(pctx);
690 break;
691 case SYS_exit:
692 if (pctx_lwpiterate(pctx, pctx->fini_lwp)
693 != 0)
694 running = -1;
695 pctx->exit(pctx, pid, lwpid,
696 (int)pstatus->pr_lwp.pr_sysarg[0],
697 pctx->uarg);
698 if (running == 1)
699 running = 0;
700 break;
701 case SYS_execve:
702 (void) pctx_lwpiterate(pctx, pctx->fini_lwp);
703 break;
704 default:
705 pctx_error(pctx, fn,
706 "warning - pid %d sysentry(%d)\n",
707 (int)pid, pstatus->pr_lwp.pr_what);
708 break;
709 }
710 break;
711 case PR_SYSEXIT:
712 switch (pstatus->pr_lwp.pr_what) {
713 case SYS_execve:
714 if (pstatus->pr_lwp.pr_errno) {
715 /*
716 * The exec failed completely.
717 * Reinstate the lwps we fini'd
718 * at exec entrance
719 */
720 if (pctx_lwpiterate(pctx,
721 pctx->init_lwp) == 0)
722 running = 1;
723 else
724 running = -1;
725 break;
726 }
727 if ((uintptr_t)pctx->exec ==
728 (uintptr_t)default_int) {
729 running = 0;
730 break;
731 }
732 (void) memcpy(&psinfo,
733 Ppsinfo(pctx->Pr), sizeof (psinfo));
734 proc_unctrl_psinfo(&psinfo);
735 pctx_begin_syscalls(pctx);
736 if (pctx->exec(pctx, pid, lwpid,
737 psinfo.pr_psargs, pctx->uarg) != 0)
738 running = -1;
739 if (running == 1 && pctx->init_lwp(pctx,
740 pid, 1, pctx->uarg) != 0)
741 running = -1;
742 pctx_end_syscalls(pctx);
743 break;
744 case SYS_lwp_create:
745 if (pstatus->pr_lwp.pr_errno ||
746 pstatus->pr_lwp.pr_rval1)
747 break;
748 pctx_begin_syscalls(pctx);
749 if (pctx->init_lwp(pctx, pid, lwpid,
750 pctx->uarg) != 0)
751 running = -1;
752 if (running == 1 && pctx->lwp_create(pctx,
753 pid, lwpid, pctx->uarg) != 0)
754 running = -1;
755 pctx_end_syscalls(pctx);
756 break;
757 case SYS_vfork:
758 case SYS_forksys:
759 if (pstatus->pr_lwp.pr_errno)
760 break;
761 (void) fflush(NULL);
762 switch (fork1()) {
763 pid_t ppid;
764 int wascreated;
765 pctx_sysc_forkfn_t *forkfn;
766 case 0:
767 ppid = pid;
768 pid = pstatus->pr_lwp.pr_rval1;
769 wascreated = pctx->created;
770 forkfn = pctx->fork;
771 pctx_free(pctx);
772 pctx = pctx_capture(pid, pctx->uarg,
773 pctx->verbose, pctx->errfn);
774 if (pctx != NULL) {
775 if (wascreated) {
776 /*
777 * Set kill on last
778 * close so -all-
779 * children die.
780 */
781 pctx->created = 1;
782 (void) Psetflags(
783 pctx->Pr, PR_KLC);
784 }
785 (*forkfn)(pctx, ppid, pid,
786 lwpid, pctx->uarg);
787 pctx_release(pctx);
788 _exit(0);
789 } else {
790 _exit(1);
791 }
792 /*NOTREACHED*/
793 case -1:
794 pctx_error(pctx, fn,
795 "cannot follow pid %d: %s\n",
796 (int)pstatus->pr_lwp.pr_rval1,
797 strerror(errno));
798 break;
799 default:
800 break;
801 }
802 break;
803 default:
804 pctx_error(pctx, fn, gettext(
805 "warning - pid %d sysexit(%d)\n"),
806 (int)pid, pstatus->pr_lwp.pr_what);
807 break;
808 }
809 break;
810 case PR_SIGNALLED:
811 if (pctx->verbose)
812 pctx_error(pctx, fn,
813 gettext("pid %d - signalled\n"), (int)pid);
814 break;
815 case PR_JOBCONTROL:
816 if (pctx->verbose)
817 pctx_error(pctx, fn,
818 gettext("pid %d - job control stop\n"),
819 (int)pid);
820 running = -1;
821 break;
822 case PR_FAULTED:
823 if (pctx->verbose)
824 pctx_error(pctx, fn,
825 gettext("pid %d - faulted\n"), (int)pid);
826 break;
827 case PR_SUSPENDED:
828 if (pctx->verbose)
829 pctx_error(pctx, fn,
830 gettext("pid %d - suspended\n"), (int)pid);
831 break;
832 case PR_CHECKPOINT:
833 if (pctx->verbose)
834 pctx_error(pctx, fn,
835 gettext("pid %d - checkpoint\n"),
836 (int)pid);
837 break;
838 default:
839 if (pctx->verbose)
840 pctx_error(pctx, fn,
841 gettext("pid %d - reason %d\n"),
842 (int)pid, pstatus->pr_lwp.pr_why);
843 running = -1;
844 break;
845 }
846 }
847
848 bailout:
849 (void) signal(SIGCHLD, sigsaved);
850
851 if (pctx->terminate)
852 return (0);
853
854 switch (running) {
855 case 0:
856 return (0);
857 case -1:
858 return (-1);
859 default:
860 pctx_error(pctx, fn, gettext("lost control of pid %d\n"),
861 (int)pid);
862 pctx_free(pctx);
863 return (-1);
864 }
865 }
866
867 /*
868 * Execute the private 'cpc' system call in the context of the
869 * controlled process.
870 */
871 int
__pctx_cpc(pctx_t * pctx,cpc_t * cpc,int cmd,id_t lwpid,void * data1,void * data2,void * data3,int bufsize)872 __pctx_cpc(pctx_t *pctx, cpc_t *cpc,
873 int cmd, id_t lwpid, void *data1, void *data2, void *data3, int bufsize)
874 {
875 sysret_t rval;
876 argdes_t argd[5];
877 argdes_t *adp = &argd[0];
878 int error;
879
880 /*
881 * Keep track of the relationship between cpc_t and pctx_t here.
882 * We store the last cpc_t used by libpctx, so that when this pctx is
883 * destroyed, libpctx can notify libcpc.
884 */
885
886 if (pctx->cpc != NULL && pctx->cpc != cpc && pctx_cpc_callback != NULL)
887 (*pctx_cpc_callback)(pctx->cpc, pctx);
888 pctx->cpc = cpc;
889
890 /*
891 * cmd and lwpid are passed in by value no matter what the command is.
892 */
893 adp->arg_value = cmd;
894 adp->arg_object = NULL;
895 adp->arg_type = AT_BYVAL;
896 adp->arg_inout = AI_INPUT;
897 adp->arg_size = 0;
898 adp++;
899
900 adp->arg_value = lwpid;
901 adp->arg_object = NULL;
902 adp->arg_type = AT_BYVAL;
903 adp->arg_inout = AI_INPUT;
904 adp->arg_size = 0;
905 adp++;
906
907 switch (cmd) {
908 case CPC_BIND:
909 adp->arg_value = 0;
910 adp->arg_object = data1;
911 adp->arg_type = AT_BYREF;
912 adp->arg_inout = AI_INPUT;
913 adp->arg_size = (size_t)data2;
914 adp++;
915
916 adp->arg_value = (size_t)data2;
917 adp->arg_object = NULL;
918 adp->arg_type = AT_BYVAL;
919 adp->arg_inout = AI_INPUT;
920 adp->arg_size = 0;
921 adp++;
922
923 adp->arg_value = 0;
924 adp->arg_object = data3;
925 adp->arg_type = AT_BYREF;
926 adp->arg_inout = AI_INOUT;
927 adp->arg_size = sizeof (int);
928
929 break;
930 case CPC_SAMPLE:
931 adp->arg_value = 0;
932 adp->arg_object = data1;
933 adp->arg_type = AT_BYREF;
934 adp->arg_inout = AI_OUTPUT;
935 adp->arg_size = bufsize;
936 adp++;
937
938 adp->arg_value = 0;
939 adp->arg_object = data2;
940 adp->arg_type = AT_BYREF;
941 adp->arg_inout = AI_OUTPUT;
942 adp->arg_size = sizeof (hrtime_t);
943 adp++;
944
945 adp->arg_value = 0;
946 adp->arg_object = data3;
947 adp->arg_type = AT_BYREF;
948 adp->arg_inout = AI_OUTPUT;
949 adp->arg_size = sizeof (uint64_t);
950
951 break;
952 default:
953 adp->arg_value = 0;
954 adp->arg_object = 0;
955 adp->arg_type = AT_BYVAL;
956 adp->arg_inout = AI_INPUT;
957 adp->arg_size = 0;
958 adp++;
959
960 adp->arg_value = 0;
961 adp->arg_object = 0;
962 adp->arg_type = AT_BYVAL;
963 adp->arg_inout = AI_INPUT;
964 adp->arg_size = 0;
965 adp++;
966
967 adp->arg_value = 0;
968 adp->arg_object = 0;
969 adp->arg_type = AT_BYVAL;
970 adp->arg_inout = AI_INPUT;
971 adp->arg_size = 0;
972
973 break;
974 }
975
976 error = Psyscall(pctx->Pr, &rval, SYS_cpc, 5, &argd[0]);
977
978 if (error) {
979 errno = error > 0 ? error : ENOSYS;
980 return (-1);
981 }
982 return (rval.sys_rval1);
983 }
984
985 /*
986 * libcpc-private hook used to register a callback. The callback is used to
987 * notify libcpc when a pctx handle is invalidated.
988 */
989 void
__pctx_cpc_register_callback(void (* arg)(struct __cpc *,struct __pctx *))990 __pctx_cpc_register_callback(void (*arg)(struct __cpc *, struct __pctx *))
991 {
992 pctx_cpc_callback = arg;
993 }
994
995 /*
996 * Tell pctx_run to bail out immediately
997 */
998 void
pctx_terminate(struct __pctx * pctx)999 pctx_terminate(struct __pctx *pctx)
1000 {
1001 pctx->terminate = 1;
1002 }
1003