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 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 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 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 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 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 }