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 * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <unistd.h>
31 #include <ctype.h>
32 #include <fcntl.h>
33 #include <string.h>
34 #include <memory.h>
35 #include <errno.h>
36 #include <dirent.h>
37 #include <limits.h>
38 #include <signal.h>
39 #include <sys/types.h>
40 #include <sys/uio.h>
41 #include <sys/stat.h>
42 #include <sys/resource.h>
43 #include <sys/param.h>
44 #include <sys/stack.h>
45 #include <sys/fault.h>
46 #include <sys/syscall.h>
47 #include <sys/sysmacros.h>
48
49 #include "libproc.h"
50 #include "Pcontrol.h"
51 #include "Putil.h"
52 #include "P32ton.h"
53 #include "Pisadep.h"
54
55 extern sigset_t blockable_sigs;
56
57 static void
Pabort_agent(struct ps_prochandle * P)58 Pabort_agent(struct ps_prochandle *P)
59 {
60 int sysnum = P->status.pr_lwp.pr_syscall;
61 int stop;
62
63 dprintf("agent LWP is asleep in syscall %d\n", sysnum);
64 (void) Pstop(P, 0);
65 stop = Psysexit(P, sysnum, TRUE);
66
67 if (Psetrun(P, 0, PRSABORT) == 0) {
68 while (Pwait(P, 0) == -1 && errno == EINTR)
69 continue;
70 (void) Psysexit(P, sysnum, stop);
71 dprintf("agent LWP system call aborted\n");
72 }
73 }
74
75 /*
76 * Create the /proc agent LWP for further operations.
77 */
78 int
Pcreate_agent(struct ps_prochandle * P)79 Pcreate_agent(struct ps_prochandle *P)
80 {
81 int fd;
82 char pathname[PATH_MAX];
83 char *fname;
84 struct {
85 long cmd;
86 prgregset_t regs;
87 } cmd;
88
89 /*
90 * If not first reference, we already have the /proc agent LWP active.
91 */
92 if (P->agentcnt > 0) {
93 P->agentcnt++;
94 return (0);
95 }
96
97 /*
98 * The agent is not available for use as a mortician or as an
99 * obstetrician.
100 */
101 if (P->state == PS_DEAD || P->state == PS_UNDEAD ||
102 P->state == PS_IDLE) {
103 errno = ENOENT;
104 return (-1);
105 }
106
107 /*
108 * Create the special /proc agent LWP if it doesn't already exist.
109 * Give it the registers of the representative LWP.
110 */
111 (void) Pstop(P, 0);
112 Psync(P);
113 if (!(P->status.pr_lwp.pr_flags & PR_AGENT)) {
114 cmd.cmd = PCAGENT;
115 (void) memcpy(&cmd.regs, &P->status.pr_lwp.pr_reg[0],
116 sizeof (P->status.pr_lwp.pr_reg));
117 if (write(P->ctlfd, &cmd, sizeof (cmd)) != sizeof (cmd))
118 goto bad;
119 }
120
121 /* refresh the process status */
122 (void) Pstopstatus(P, PCNULL, 0);
123
124 /* open the agent LWP files */
125 (void) snprintf(pathname, sizeof (pathname), "%s/%d/lwp/agent/",
126 procfs_path, (int)P->pid);
127 fname = pathname + strlen(pathname);
128 (void) set_minfd();
129
130 /*
131 * It is difficult to know how to recover from the two errors
132 * that follow. The agent LWP exists and we need to kill it,
133 * but we can't because we need it active in order to kill it.
134 * We just hope that these failures never occur.
135 */
136 (void) strcpy(fname, "lwpstatus");
137 if ((fd = open(pathname, O_RDONLY)) < 0 ||
138 (fd = dupfd(fd, 0)) < 0)
139 goto bad;
140 P->agentstatfd = fd;
141
142 (void) strcpy(fname, "lwpctl");
143 if ((fd = open(pathname, O_WRONLY)) < 0 ||
144 (fd = dupfd(fd, 0)) < 0)
145 goto bad;
146 P->agentctlfd = fd;
147
148 /*
149 * If the agent is currently asleep in a system call, attempt
150 * to abort the system call so it's ready to serve.
151 */
152 if (P->status.pr_lwp.pr_flags & PR_ASLEEP) {
153 dprintf("Pcreate_agent: aborting agent syscall\n");
154 Pabort_agent(P);
155 }
156
157 /* get the agent LWP status */
158 P->agentcnt++;
159 if (Pstopstatus(P, PCNULL, 0) != 0) {
160 Pdestroy_agent(P);
161 return (-1);
162 }
163
164 return (0);
165
166 bad:
167 if (P->agentstatfd >= 0)
168 (void) close(P->agentstatfd);
169 if (P->agentctlfd >= 0)
170 (void) close(P->agentctlfd);
171 P->agentstatfd = -1;
172 P->agentctlfd = -1;
173 /* refresh the process status */
174 (void) Pstopstatus(P, PCNULL, 0);
175 return (-1);
176 }
177
178 /*
179 * Decrement the /proc agent agent reference count.
180 * On last reference, destroy the agent.
181 */
182 void
Pdestroy_agent(struct ps_prochandle * P)183 Pdestroy_agent(struct ps_prochandle *P)
184 {
185 if (P->agentcnt > 1)
186 P->agentcnt--;
187 else {
188 int flags;
189
190 Psync(P); /* Flush out any pending changes */
191
192 (void) Pstopstatus(P, PCNULL, 0);
193 flags = P->status.pr_lwp.pr_flags;
194
195 /*
196 * If the agent is currently asleep in a system call, attempt
197 * to abort the system call so we can terminate the agent.
198 */
199 if ((flags & (PR_AGENT|PR_ASLEEP)) == (PR_AGENT|PR_ASLEEP)) {
200 dprintf("Pdestroy_agent: aborting agent syscall\n");
201 Pabort_agent(P);
202 }
203
204 /*
205 * The agent itself is destroyed by forcing it to execute
206 * the _lwp_exit(2) system call. Close our agent descriptors
207 * regardless of whether this is successful.
208 */
209 (void) pr_lwp_exit(P);
210 (void) close(P->agentctlfd);
211 (void) close(P->agentstatfd);
212 P->agentctlfd = -1;
213 P->agentstatfd = -1;
214 P->agentcnt = 0;
215
216 /*
217 * Now that (hopefully) the agent has exited, refresh the
218 * status: the representative LWP is no longer the agent.
219 */
220 (void) Pstopstatus(P, PCNULL, 0);
221 }
222 }
223
224 /*
225 * Execute the syscall instruction.
226 */
227 static int
execute(struct ps_prochandle * P,int sysindex)228 execute(struct ps_prochandle *P, int sysindex)
229 {
230 int ctlfd = (P->agentctlfd >= 0)? P->agentctlfd : P->ctlfd;
231 int washeld = FALSE;
232 sigset_t hold; /* mask of held signals */
233 int cursig;
234 struct {
235 long cmd;
236 siginfo_t siginfo;
237 } ctl;
238 int sentry; /* old value of stop-on-syscall-entry */
239
240 sentry = Psysentry(P, sysindex, TRUE); /* set stop-on-syscall-entry */
241
242 /*
243 * If not already blocked, block all signals now.
244 */
245 if (memcmp(&P->status.pr_lwp.pr_lwphold, &blockable_sigs,
246 sizeof (sigset_t)) != 0) {
247 hold = P->status.pr_lwp.pr_lwphold;
248 P->status.pr_lwp.pr_lwphold = blockable_sigs;
249 P->flags |= SETHOLD;
250 washeld = TRUE;
251 }
252
253 /*
254 * If there is a current signal, remember it and cancel it.
255 */
256 if ((cursig = P->status.pr_lwp.pr_cursig) != 0) {
257 ctl.cmd = PCSSIG;
258 ctl.siginfo = P->status.pr_lwp.pr_info;
259 }
260
261 if (Psetrun(P, 0, PRCSIG | PRCFAULT) == -1)
262 goto bad;
263
264 while (P->state == PS_RUN) {
265 (void) Pwait(P, 0);
266 }
267 if (P->state != PS_STOP)
268 goto bad;
269
270 if (cursig) /* restore cursig */
271 (void) write(ctlfd, &ctl, sizeof (ctl));
272 if (washeld) { /* restore the signal mask if we set it */
273 P->status.pr_lwp.pr_lwphold = hold;
274 P->flags |= SETHOLD;
275 }
276
277 (void) Psysentry(P, sysindex, sentry); /* restore sysentry stop */
278
279 if (P->status.pr_lwp.pr_why == PR_SYSENTRY &&
280 P->status.pr_lwp.pr_what == sysindex)
281 return (0);
282 bad:
283 return (-1);
284 }
285
286
287 /*
288 * Perform system call in controlled process.
289 */
290 int
Psyscall(struct ps_prochandle * P,sysret_t * rval,int sysindex,uint_t nargs,argdes_t * argp)291 Psyscall(struct ps_prochandle *P,
292 sysret_t *rval, /* syscall return values */
293 int sysindex, /* system call index */
294 uint_t nargs, /* number of arguments to system call */
295 argdes_t *argp) /* argument descriptor array */
296 {
297 int agent_created = FALSE;
298 pstatus_t save_pstatus;
299 argdes_t *adp; /* pointer to argument descriptor */
300 int i; /* general index value */
301 int model; /* data model */
302 int error = 0; /* syscall errno */
303 int Perr = 0; /* local error number */
304 int sexit; /* old value of stop-on-syscall-exit */
305 prgreg_t sp; /* adjusted stack pointer */
306 prgreg_t ap; /* adjusted argument pointer */
307 sigset_t unblock;
308
309 (void) sigprocmask(SIG_BLOCK, &blockable_sigs, &unblock);
310
311 rval->sys_rval1 = 0; /* initialize return values */
312 rval->sys_rval2 = 0;
313
314 if (sysindex <= 0 || sysindex > PRMAXSYS || nargs > MAXARGS)
315 goto bad1; /* programming error */
316
317 if (P->state == PS_DEAD || P->state == PS_UNDEAD || P->state == PS_IDLE)
318 goto bad1; /* dead processes can't perform system calls */
319
320 model = P->status.pr_dmodel;
321 #ifndef _LP64
322 /* We must be a 64-bit process to deal with a 64-bit process */
323 if (model == PR_MODEL_LP64)
324 goto bad9;
325 #endif
326
327 /*
328 * Create the /proc agent LWP in the process to do all the work.
329 * (It may already exist; nested create/destroy is permitted
330 * by virtue of the reference count.)
331 */
332 if (Pcreate_agent(P) != 0)
333 goto bad8;
334
335 /*
336 * Save agent's status to restore on exit.
337 */
338 agent_created = TRUE;
339 save_pstatus = P->status;
340
341 if (P->state != PS_STOP || /* check state of LWP */
342 (P->status.pr_flags & PR_ASLEEP))
343 goto bad2;
344
345 if (Pscantext(P)) /* bad text ? */
346 goto bad3;
347
348 /*
349 * Validate arguments and compute the stack frame parameters.
350 * Begin with the current stack pointer.
351 */
352 #ifdef _LP64
353 if (model == PR_MODEL_LP64) {
354 sp = P->status.pr_lwp.pr_reg[R_SP] + STACK_BIAS;
355 sp = PSTACK_ALIGN64(sp);
356 } else {
357 #endif
358 sp = (uint32_t)P->status.pr_lwp.pr_reg[R_SP];
359 sp = PSTACK_ALIGN32(sp);
360 #ifdef _LP64
361 }
362 #endif
363
364 /*
365 * For each AT_BYREF argument, compute the necessary
366 * stack space and the object's stack address.
367 */
368 for (i = 0, adp = argp; i < nargs; i++, adp++) {
369 rval->sys_rval1 = i; /* in case of error */
370 switch (adp->arg_type) {
371 default: /* programming error */
372 goto bad4;
373 case AT_BYVAL: /* simple argument */
374 break;
375 case AT_BYREF: /* must allocate space */
376 switch (adp->arg_inout) {
377 case AI_INPUT:
378 case AI_OUTPUT:
379 case AI_INOUT:
380 if (adp->arg_object == NULL)
381 goto bad5; /* programming error */
382 break;
383 default: /* programming error */
384 goto bad6;
385 }
386 /* allocate stack space for BYREF argument */
387 if (adp->arg_size == 0 || adp->arg_size > MAXARGL)
388 goto bad7; /* programming error */
389 #ifdef _LP64
390 if (model == PR_MODEL_LP64)
391 sp = PSTACK_ALIGN64(sp - adp->arg_size);
392 else
393 #endif
394 sp = PSTACK_ALIGN32(sp - adp->arg_size);
395 adp->arg_value = sp; /* stack address for object */
396 break;
397 }
398 }
399 rval->sys_rval1 = 0; /* in case of error */
400 /*
401 * Point of no return.
402 * Perform the system call entry, adjusting %sp.
403 * This moves the LWP to the stopped-on-syscall-entry state
404 * just before the arguments to the system call are fetched.
405 */
406 ap = Psyscall_setup(P, nargs, sysindex, sp);
407 P->flags |= SETREGS; /* set registers before continuing */
408 dprintf("Psyscall(): execute(sysindex = %d)\n", sysindex);
409
410 /*
411 * Execute the syscall instruction and stop on syscall entry.
412 */
413 if (execute(P, sysindex) != 0 ||
414 (!Pissyscall(P, P->status.pr_lwp.pr_reg[R_PC]) &&
415 !Pissyscall_prev(P, P->status.pr_lwp.pr_reg[R_PC], NULL)))
416 goto bad10;
417
418 dprintf("Psyscall(): copying arguments\n");
419
420 /*
421 * The LWP is stopped at syscall entry.
422 * Copy objects to stack frame for each argument.
423 */
424 for (i = 0, adp = argp; i < nargs; i++, adp++) {
425 rval->sys_rval1 = i; /* in case of error */
426 if (adp->arg_type != AT_BYVAL &&
427 adp->arg_inout != AI_OUTPUT) {
428 /* copy input byref parameter to process */
429 if (Pwrite(P, adp->arg_object, adp->arg_size,
430 (uintptr_t)adp->arg_value) != adp->arg_size)
431 goto bad17;
432 }
433 }
434 rval->sys_rval1 = 0; /* in case of error */
435 if (Psyscall_copyinargs(P, nargs, argp, ap) != 0)
436 goto bad18;
437
438 /*
439 * Complete the system call.
440 * This moves the LWP to the stopped-on-syscall-exit state.
441 */
442 dprintf("Psyscall(): set running at sysentry\n");
443
444 sexit = Psysexit(P, sysindex, TRUE); /* catch this syscall exit */
445 do {
446 if (Psetrun(P, 0, 0) == -1)
447 goto bad21;
448 while (P->state == PS_RUN)
449 (void) Pwait(P, 0);
450 } while (P->state == PS_STOP && P->status.pr_lwp.pr_why != PR_SYSEXIT);
451 (void) Psysexit(P, sysindex, sexit); /* restore original setting */
452
453 /*
454 * If the system call was _lwp_exit(), we expect that our last call
455 * to Pwait() will yield ENOENT because the LWP no longer exists.
456 */
457 if (sysindex == SYS_lwp_exit && errno == ENOENT) {
458 dprintf("Psyscall(): _lwp_exit successful\n");
459 rval->sys_rval1 = rval->sys_rval2 = 0;
460 goto out;
461 }
462
463 if (P->state != PS_STOP || P->status.pr_lwp.pr_why != PR_SYSEXIT)
464 goto bad22;
465
466 if (P->status.pr_lwp.pr_what != sysindex)
467 goto bad23;
468
469 if (!Pissyscall_prev(P, P->status.pr_lwp.pr_reg[R_PC], NULL)) {
470 dprintf("Pissyscall_prev() failed\n");
471 goto bad24;
472 }
473
474 dprintf("Psyscall(): caught at sysexit\n");
475
476 /*
477 * For each argument.
478 */
479 for (i = 0, adp = argp; i < nargs; i++, adp++) {
480 rval->sys_rval1 = i; /* in case of error */
481 if (adp->arg_type != AT_BYVAL &&
482 adp->arg_inout != AI_INPUT) {
483 /* copy output byref parameter from process */
484 if (Pread(P, adp->arg_object, adp->arg_size,
485 (uintptr_t)adp->arg_value) != adp->arg_size)
486 goto bad25;
487 }
488 }
489
490 if (Psyscall_copyoutargs(P, nargs, argp, ap) != 0)
491 goto bad26;
492
493 /*
494 * Get the return values from the syscall.
495 */
496 if (P->status.pr_lwp.pr_errno) { /* error return */
497 error = P->status.pr_lwp.pr_errno;
498 rval->sys_rval1 = -1L;
499 rval->sys_rval2 = -1L;
500 dprintf("Psyscall(%d) fails with errno %d\n",
501 sysindex, error);
502 } else { /* normal return */
503 rval->sys_rval1 = P->status.pr_lwp.pr_rval1;
504 rval->sys_rval2 = P->status.pr_lwp.pr_rval2;
505 dprintf("Psyscall(%d) returns 0x%lx 0x%lx\n", sysindex,
506 P->status.pr_lwp.pr_rval1, P->status.pr_lwp.pr_rval2);
507 }
508
509 goto out;
510
511 bad26: Perr++;
512 bad25: Perr++;
513 bad24: Perr++;
514 bad23: Perr++;
515 bad22: Perr++;
516 bad21: Perr++;
517 Perr++;
518 Perr++;
519 bad18: Perr++;
520 bad17: Perr++;
521 Perr++;
522 Perr++;
523 Perr++;
524 Perr++;
525 Perr++;
526 Perr++;
527 bad10: Perr++;
528 bad9: Perr++;
529 bad8: Perr++;
530 bad7: Perr++;
531 bad6: Perr++;
532 bad5: Perr++;
533 bad4: Perr++;
534 bad3: Perr++;
535 bad2: Perr++;
536 bad1: Perr++;
537 error = -1;
538 dprintf("Psyscall(%d) fails with local error %d\n", sysindex, Perr);
539
540 out:
541 /*
542 * Destroy the /proc agent LWP now (or just bump down the ref count).
543 */
544 if (agent_created) {
545 if (P->state != PS_UNDEAD) {
546 P->status = save_pstatus;
547 P->flags |= SETREGS;
548 Psync(P);
549 }
550 Pdestroy_agent(P);
551 }
552
553 (void) sigprocmask(SIG_SETMASK, &unblock, NULL);
554 return (error);
555 }
556