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