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 }