Print this page
    
15254 %ymm registers not restored after signal handler
15367 x86 getfpregs() summons corrupting %xmm ghosts
15333 want x86 /proc xregs support (libc_db, libproc, mdb, etc.)
15336 want libc functions for extended ucontext_t
15334 want ps_lwphandle-specific reg routines
15328 FPU_CW_INIT mistreats reserved bit
15335 i86pc fpu_subr.c isn't really platform-specific
15332 setcontext(2) isn't actually noreturn
15331 need <sys/stdalign.h>
Change-Id: I7060aa86042dfb989f77fc3323c065ea2eafa9ad
Conflicts:
    usr/src/uts/common/fs/proc/prcontrol.c
    usr/src/uts/intel/os/archdep.c
    usr/src/uts/intel/sys/ucontext.h
    usr/src/uts/intel/syscall/getcontext.c
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/uts/common/fs/proc/prioctl.c
          +++ new/usr/src/uts/common/fs/proc/prioctl.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  
    | 
      ↓ open down ↓ | 
    15 lines elided | 
    
      ↑ open up ↑ | 
  
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
  24   24   * Use is subject to license terms.
  25   25   * Copyright 2019 Joyent, Inc.
       26 + * Copyright 2023 Oxide Computer Company
  26   27   */
  27   28  
  28   29  /*      Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
  29   30  /*        All rights reserved.  */
  30   31  
  31   32  #include <sys/types.h>
  32   33  #include <sys/param.h>
  33   34  #include <sys/vmparam.h>
  34   35  #include <sys/var.h>
  35   36  #include <sys/cmn_err.h>
  36   37  #include <sys/cred.h>
  37   38  #include <sys/debug.h>
  38   39  #include <sys/errno.h>
  39   40  #include <sys/file.h>
  40   41  #include <sys/inline.h>
  41   42  #include <sys/kmem.h>
  42   43  #include <sys/proc.h>
  43   44  #include <sys/brand.h>
  44   45  #include <sys/sysmacros.h>
  45   46  #include <sys/systm.h>
  46   47  #include <sys/vfs.h>
  47   48  #include <sys/vnode.h>
  48   49  #include <sys/cpuvar.h>
  49   50  #include <sys/session.h>
  50   51  #include <sys/signal.h>
  51   52  #include <sys/auxv.h>
  52   53  #include <sys/user.h>
  53   54  #include <sys/disp.h>
  54   55  #include <sys/class.h>
  55   56  #include <sys/ts.h>
  56   57  #include <sys/mman.h>
  57   58  #include <sys/fault.h>
  58   59  #include <sys/syscall.h>
  59   60  #include <sys/schedctl.h>
  60   61  #include <sys/pset.h>
  61   62  #include <sys/old_procfs.h>
  62   63  #include <sys/zone.h>
  63   64  #include <sys/time.h>
  64   65  #include <sys/msacct.h>
  65   66  #include <vm/rm.h>
  66   67  #include <vm/as.h>
  67   68  #include <vm/rm.h>
  68   69  #include <vm/seg.h>
  69   70  #include <vm/seg_vn.h>
  70   71  #include <sys/contract_impl.h>
  71   72  #include <sys/ctfs_impl.h>
  72   73  #include <sys/ctfs.h>
  73   74  
  74   75  #if defined(__i386_COMPAT)
  75   76  #include <sys/sysi86.h>
  76   77  #endif
  77   78  
  78   79  #include <fs/proc/prdata.h>
  79   80  
  80   81  static  int     isprwrioctl(int);
  81   82  static  ulong_t prmaprunflags(long);
  82   83  static  long    prmapsetflags(long);
  83   84  static  void    prsetrun(kthread_t *, prrun_t *);
  84   85  static  int     propenm(prnode_t *, caddr_t, caddr_t, int *, cred_t *);
  85   86  extern  void    oprgetstatus(kthread_t *, prstatus_t *, zone_t *);
  86   87  extern  void    oprgetpsinfo(proc_t *, prpsinfo_t *, kthread_t *);
  87   88  static  int     oprgetmap(proc_t *, list_t *);
  88   89  
  89   90  static int
  90   91  prctioctl(prnode_t *pnp, int cmd, intptr_t arg, int flag, cred_t *cr)
  91   92  {
  92   93          int error = 0;
  93   94          ct_kparam_t kparam;
  94   95          ct_param_t *param = &kparam.param;
  95   96          ct_template_t *tmpl;
  96   97  
  97   98          if (cmd != CT_TSET && cmd != CT_TGET)
  98   99                  return (EINVAL);
  99  100  
 100  101          error = ctparam_copyin((void *)arg, &kparam, flag, cmd);
 101  102          if (error != 0)
 102  103                  return (error);
 103  104  
 104  105          if ((error = prlock(pnp, ZNO)) != 0) {
 105  106                  kmem_free(kparam.ctpm_kbuf, param->ctpm_size);
 106  107                  return (error);
 107  108          }
 108  109  
 109  110          tmpl = pnp->pr_common->prc_thread->t_lwp->lwp_ct_active[pnp->pr_cttype];
 110  111          if (tmpl == NULL) {
 111  112                  prunlock(pnp);
 112  113                  kmem_free(kparam.ctpm_kbuf, param->ctpm_size);
 113  114                  return (ESTALE);
 114  115          }
 115  116  
 116  117          if (cmd == CT_TSET)
 117  118                  error = ctmpl_set(tmpl, &kparam, cr);
 118  119          else
 119  120                  error = ctmpl_get(tmpl, &kparam);
 120  121  
 121  122          prunlock(pnp);
 122  123  
 123  124          if (cmd == CT_TGET && error == 0) {
 124  125                  error = ctparam_copyout(&kparam, (void *)arg, flag);
 125  126          } else {
 126  127                  kmem_free(kparam.ctpm_kbuf, param->ctpm_size);
 127  128          }
 128  129  
 129  130          return (error);
 130  131  }
 131  132  
 132  133  
 133  134  /*
 134  135   * Control operations (lots).
 135  136   */
 136  137  /* BEGIN CSTYLED */
 137  138  /*ARGSUSED*/
 138  139  #ifdef _SYSCALL32_IMPL
 139  140  static int
 140  141  prioctl64(struct vnode *vp, int cmd, intptr_t arg, int flag, cred_t *cr,
 141  142      int *rvalp, caller_context_t *ct)
 142  143  #else
 143  144  int
 144  145  prioctl(struct vnode *vp, int cmd, intptr_t arg, int flag, cred_t *cr,
 145  146      int *rvalp, caller_context_t *ct)
 146  147  #endif  /* _SYSCALL32_IMPL */
 147  148  {
 148  149  /* END CSTYLED */
 149  150          int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
 150  151          caddr_t cmaddr = (caddr_t)arg;
 151  152          proc_t *p;
 152  153          user_t *up;
 153  154          kthread_t *t;
 154  155          klwp_t *lwp;
 155  156          prnode_t *pnp = VTOP(vp);
 156  157          prcommon_t *pcp;
 157  158          prnode_t *xpnp = NULL;
 158  159          int error;
 159  160          int zdisp;
 160  161          void *thing = NULL;
 161  162          size_t thingsize = 0;
 162  163  
 163  164          /*
 164  165           * For copyin()/copyout().
 165  166           */
 166  167          union {
 167  168                  caddr_t         va;
 168  169                  int             signo;
 169  170                  int             nice;
 170  171                  uint_t          lwpid;
 171  172                  long            flags;
 172  173                  prstatus_t      prstat;
 173  174                  prrun_t         prrun;
 174  175                  sigset_t        smask;
 175  176                  siginfo_t       info;
 176  177                  sysset_t        prmask;
 177  178                  prgregset_t     regs;
 178  179                  prfpregset_t    fpregs;
 179  180                  prpsinfo_t      prps;
 180  181                  sigset_t        holdmask;
 181  182                  fltset_t        fltmask;
 182  183                  prcred_t        prcred;
 183  184                  prhusage_t      prhusage;
 184  185                  prmap_t         prmap;
 185  186                  auxv_t          auxv[__KERN_NAUXV_IMPL];
 186  187          } un;
 187  188  
 188  189          if (pnp->pr_type == PR_TMPL)
 189  190                  return (prctioctl(pnp, cmd, arg, flag, cr));
 190  191  
 191  192          /*
 192  193           * Support for old /proc interface.
 193  194           */
 194  195          if (pnp->pr_pidfile != NULL) {
 195  196                  ASSERT(pnp->pr_type == PR_PIDDIR);
 196  197                  vp = pnp->pr_pidfile;
 197  198                  pnp = VTOP(vp);
 198  199                  ASSERT(pnp->pr_type == PR_PIDFILE);
 199  200          }
 200  201  
 201  202          if (pnp->pr_type != PR_PIDFILE && pnp->pr_type != PR_LWPIDFILE)
  
    | 
      ↓ open down ↓ | 
    166 lines elided | 
    
      ↑ open up ↑ | 
  
 202  203                  return (ENOTTY);
 203  204  
 204  205          /*
 205  206           * Fail ioctls which are logically "write" requests unless
 206  207           * the user has write permission.
 207  208           */
 208  209          if ((flag & FWRITE) == 0 && isprwrioctl(cmd))
 209  210                  return (EBADF);
 210  211  
 211  212          /*
      213 +         * The following commands are no longer supported. They were present on
      214 +         * SPARC and were always errors on other platforms. We now explicitly
      215 +         * return ENOTSUP to indicate that this is no longer done.
      216 +         */
      217 +        switch (cmd) {
      218 +        case PIOCSXREG:
      219 +                return (ENOTSUP);
      220 +        default:
      221 +                break;
      222 +        }
      223 +
      224 +        /*
 212  225           * Perform any necessary copyin() operations before
 213  226           * locking the process.  Helps avoid deadlocks and
 214  227           * improves performance.
 215  228           *
 216  229           * Also, detect invalid ioctl codes here to avoid
 217      -         * locking a process unnnecessarily.
      230 +         * locking a process unnecessarily.
 218  231           *
 219  232           * Also, prepare to allocate space that will be needed below,
 220  233           * case by case.
 221  234           */
 222  235          error = 0;
 223  236          switch (cmd) {
 224  237          case PIOCGETPR:
 225  238                  thingsize = sizeof (proc_t);
 226  239                  break;
 227  240          case PIOCGETU:
 228  241                  thingsize = sizeof (user_t);
 229  242                  break;
 230  243          case PIOCSTOP:
 231  244          case PIOCWSTOP:
 232  245          case PIOCLWPIDS:
 233  246          case PIOCGTRACE:
 234  247          case PIOCGENTRY:
 235  248          case PIOCGEXIT:
 236  249          case PIOCSRLC:
 237  250          case PIOCRRLC:
  
    | 
      ↓ open down ↓ | 
    10 lines elided | 
    
      ↑ open up ↑ | 
  
 238  251          case PIOCSFORK:
 239  252          case PIOCRFORK:
 240  253          case PIOCGREG:
 241  254          case PIOCGFPREG:
 242  255          case PIOCSTATUS:
 243  256          case PIOCLSTATUS:
 244  257          case PIOCPSINFO:
 245  258          case PIOCMAXSIG:
 246  259          case PIOCGXREGSIZE:
 247  260                  break;
 248      -        case PIOCSXREG:         /* set extra registers */
 249  261          case PIOCGXREG:         /* get extra registers */
 250      -#if defined(__sparc)
 251      -                thingsize = sizeof (prxregset_t);
 252      -#else
 253      -                thingsize = 0;
 254      -#endif
      262 +                thingsize = prgetprxregsize(p);
 255  263                  break;
 256  264          case PIOCACTION:
 257  265                  thingsize = (nsig-1) * sizeof (struct sigaction);
 258  266                  break;
 259  267          case PIOCGHOLD:
 260  268          case PIOCNMAP:
 261  269          case PIOCMAP:
 262  270          case PIOCGFAULT:
 263  271          case PIOCCFAULT:
 264  272          case PIOCCRED:
 265  273          case PIOCGROUPS:
 266  274          case PIOCUSAGE:
 267  275          case PIOCLUSAGE:
 268  276                  break;
 269  277          case PIOCOPENPD:
 270  278                  /*
 271  279                   * We will need this below.
 272  280                   * Allocate it now, before locking the process.
 273  281                   */
 274  282                  xpnp = prgetnode(vp, PR_OPAGEDATA);
 275  283                  break;
 276  284          case PIOCNAUXV:
 277  285          case PIOCAUXV:
 278  286                  break;
 279  287  
 280  288  #if defined(__x86)
 281  289          case PIOCNLDT:
 282  290          case PIOCLDT:
 283  291                  break;
 284  292  #endif  /* __x86 */
 285  293  
 286  294  #if defined(__sparc)
 287  295          case PIOCGWIN:
 288  296                  thingsize = sizeof (gwindows_t);
 289  297                  break;
 290  298  #endif  /* __sparc */
 291  299  
 292  300          case PIOCOPENM:         /* open mapped object for reading */
 293  301                  if (cmaddr == NULL)
 294  302                          un.va = NULL;
 295  303                  else if (copyin(cmaddr, &un.va, sizeof (un.va)))
 296  304                          error = EFAULT;
 297  305                  break;
 298  306  
 299  307          case PIOCRUN:           /* make lwp or process runnable */
 300  308                  if (cmaddr == NULL)
 301  309                          un.prrun.pr_flags = 0;
 302  310                  else if (copyin(cmaddr, &un.prrun, sizeof (un.prrun)))
 303  311                          error = EFAULT;
 304  312                  break;
 305  313  
 306  314          case PIOCOPENLWP:       /* return /proc lwp file descriptor */
 307  315                  if (copyin(cmaddr, &un.lwpid, sizeof (un.lwpid)))
 308  316                          error = EFAULT;
 309  317                  break;
 310  318  
 311  319          case PIOCSTRACE:        /* set signal trace mask */
 312  320                  if (copyin(cmaddr, &un.smask, sizeof (un.smask)))
 313  321                          error = EFAULT;
 314  322                  break;
 315  323  
 316  324          case PIOCSSIG:          /* set current signal */
 317  325                  if (cmaddr == NULL)
 318  326                          un.info.si_signo = 0;
 319  327                  else if (copyin(cmaddr, &un.info, sizeof (un.info)))
 320  328                          error = EFAULT;
 321  329                  break;
 322  330  
 323  331          case PIOCKILL:          /* send signal */
 324  332          case PIOCUNKILL:        /* delete a signal */
 325  333                  if (copyin(cmaddr, &un.signo, sizeof (un.signo)))
 326  334                          error = EFAULT;
 327  335                  break;
 328  336  
 329  337          case PIOCNICE:          /* set nice priority */
 330  338                  if (copyin(cmaddr, &un.nice, sizeof (un.nice)))
 331  339                          error = EFAULT;
 332  340                  break;
 333  341  
 334  342          case PIOCSENTRY:        /* set syscall entry bit mask */
 335  343          case PIOCSEXIT:         /* set syscall exit bit mask */
 336  344                  if (copyin(cmaddr, &un.prmask, sizeof (un.prmask)))
 337  345                          error = EFAULT;
 338  346                  break;
 339  347  
 340  348          case PIOCSET:           /* set process flags */
 341  349          case PIOCRESET:         /* reset process flags */
 342  350                  if (copyin(cmaddr, &un.flags, sizeof (un.flags)))
 343  351                          error = EFAULT;
 344  352                  break;
 345  353  
 346  354          case PIOCSREG:          /* set general registers */
 347  355                  if (copyin(cmaddr, un.regs, sizeof (un.regs)))
 348  356                          error = EFAULT;
 349  357                  break;
 350  358  
 351  359          case PIOCSFPREG:        /* set floating-point registers */
 352  360                  if (copyin(cmaddr, &un.fpregs, sizeof (un.fpregs)))
 353  361                          error = EFAULT;
 354  362                  break;
 355  363  
 356  364          case PIOCSHOLD:         /* set signal-hold mask */
 357  365                  if (copyin(cmaddr, &un.holdmask, sizeof (un.holdmask)))
 358  366                          error = EFAULT;
 359  367                  break;
 360  368  
 361  369          case PIOCSFAULT:        /* set mask of traced faults */
 362  370                  if (copyin(cmaddr, &un.fltmask, sizeof (un.fltmask)))
 363  371                          error = EFAULT;
 364  372                  break;
 365  373  
 366  374          default:
 367  375                  error = EINVAL;
 368  376                  break;
 369  377          }
 370  378  
 371  379          if (error)
 372  380                  return (error);
 373  381  
 374  382  startover:
 375  383          /*
 376  384           * If we need kmem_alloc()d space then we allocate it now, before
 377  385           * grabbing the process lock.  Using kmem_alloc(KM_SLEEP) while
 378  386           * holding the process lock leads to deadlock with the clock thread.
 379  387           * (The clock thread wakes up the pageout daemon to free up space.
 380  388           * If the clock thread blocks behind us and we are sleeping waiting
 381  389           * for space, then space may never become available.)
 382  390           */
 383  391          if (thingsize) {
 384  392                  ASSERT(thing == NULL);
  
    | 
      ↓ open down ↓ | 
    120 lines elided | 
    
      ↑ open up ↑ | 
  
 385  393                  thing = kmem_alloc(thingsize, KM_SLEEP);
 386  394          }
 387  395  
 388  396          switch (cmd) {
 389  397          case PIOCPSINFO:
 390  398          case PIOCGETPR:
 391  399          case PIOCUSAGE:
 392  400          case PIOCLUSAGE:
 393  401                  zdisp = ZYES;
 394  402                  break;
 395      -        case PIOCSXREG:         /* set extra registers */
 396      -                /*
 397      -                 * perform copyin before grabbing the process lock
 398      -                 */
 399      -                if (thing) {
 400      -                        if (copyin(cmaddr, thing, thingsize)) {
 401      -                                kmem_free(thing, thingsize);
 402      -                                return (EFAULT);
 403      -                        }
 404      -                }
 405      -                /* fall through... */
 406  403          default:
 407  404                  zdisp = ZNO;
 408  405                  break;
 409  406          }
 410  407  
 411  408          if ((error = prlock(pnp, zdisp)) != 0) {
 412  409                  if (thing != NULL)
 413  410                          kmem_free(thing, thingsize);
 414  411                  if (xpnp)
 415  412                          prfreenode(xpnp);
 416  413                  return (error);
 417  414          }
 418  415  
 419  416          pcp = pnp->pr_common;
 420  417          p = pcp->prc_proc;
 421  418          ASSERT(p != NULL);
 422  419  
 423  420          /*
 424  421           * Choose a thread/lwp for the operation.
 425  422           */
 426  423          if (zdisp == ZNO && cmd != PIOCSTOP && cmd != PIOCWSTOP) {
 427  424                  if (pnp->pr_type == PR_LWPIDFILE && cmd != PIOCLSTATUS) {
 428  425                          t = pcp->prc_thread;
 429  426                          ASSERT(t != NULL);
 430  427                  } else {
 431  428                          t = prchoose(p);        /* returns locked thread */
 432  429                          ASSERT(t != NULL);
 433  430                          thread_unlock(t);
 434  431                  }
 435  432                  lwp = ttolwp(t);
 436  433          }
 437  434  
 438  435          error = 0;
 439  436          switch (cmd) {
 440  437  
 441  438          case PIOCGETPR:         /* read struct proc */
 442  439          {
 443  440                  proc_t *prp = thing;
 444  441  
 445  442                  *prp = *p;
 446  443                  prunlock(pnp);
 447  444                  if (copyout(prp, cmaddr, sizeof (proc_t)))
 448  445                          error = EFAULT;
 449  446                  kmem_free(prp, sizeof (proc_t));
 450  447                  thing = NULL;
 451  448                  break;
 452  449          }
 453  450  
 454  451          case PIOCGETU:          /* read u-area */
 455  452          {
 456  453                  user_t *userp = thing;
 457  454  
 458  455                  up = PTOU(p);
 459  456                  *userp = *up;
 460  457                  prunlock(pnp);
 461  458                  if (copyout(userp, cmaddr, sizeof (user_t)))
 462  459                          error = EFAULT;
 463  460                  kmem_free(userp, sizeof (user_t));
 464  461                  thing = NULL;
 465  462                  break;
 466  463          }
 467  464  
 468  465          case PIOCOPENM:         /* open mapped object for reading */
 469  466                  error = propenm(pnp, cmaddr, un.va, rvalp, cr);
 470  467                  /* propenm() called prunlock(pnp) */
 471  468                  break;
 472  469  
 473  470          case PIOCSTOP:          /* stop process or lwp from running */
 474  471          case PIOCWSTOP:         /* wait for process or lwp to stop */
 475  472                  /*
 476  473                   * Can't apply to a system process.
 477  474                   */
 478  475                  if ((p->p_flag & SSYS) || p->p_as == &kas) {
 479  476                          prunlock(pnp);
 480  477                          error = EBUSY;
 481  478                          break;
 482  479                  }
 483  480  
 484  481                  if (cmd == PIOCSTOP)
 485  482                          pr_stop(pnp);
 486  483  
 487  484                  /*
 488  485                   * If an lwp is waiting for itself or its process, don't wait.
 489  486                   * The stopped lwp would never see the fact that it is stopped.
 490  487                   */
 491  488                  if ((pnp->pr_type == PR_LWPIDFILE)?
 492  489                      (pcp->prc_thread == curthread) : (p == curproc)) {
 493  490                          if (cmd == PIOCWSTOP)
 494  491                                  error = EBUSY;
 495  492                          prunlock(pnp);
 496  493                          break;
 497  494                  }
 498  495  
 499  496                  if ((error = pr_wait_stop(pnp, (time_t)0)) != 0)
 500  497                          break;  /* pr_wait_stop() unlocked the process */
 501  498  
 502  499                  if (cmaddr == NULL)
 503  500                          prunlock(pnp);
 504  501                  else {
 505  502                          /*
 506  503                           * Return process/lwp status information.
 507  504                           */
 508  505                          t = pr_thread(pnp);     /* returns locked thread */
 509  506                          thread_unlock(t);
 510  507                          oprgetstatus(t, &un.prstat, VTOZONE(vp));
 511  508                          prunlock(pnp);
 512  509                          if (copyout(&un.prstat, cmaddr, sizeof (un.prstat)))
 513  510                                  error = EFAULT;
 514  511                  }
 515  512                  break;
 516  513  
 517  514          case PIOCRUN:           /* make lwp or process runnable */
 518  515          {
 519  516                  long flags = un.prrun.pr_flags;
 520  517  
 521  518                  /*
 522  519                   * Cannot set an lwp running is it is not stopped.
 523  520                   * Also, no lwp other than the /proc agent lwp can
 524  521                   * be set running so long as the /proc agent lwp exists.
 525  522                   */
 526  523                  if ((!ISTOPPED(t) && !VSTOPPED(t) &&
 527  524                      !(t->t_proc_flag & TP_PRSTOP)) ||
 528  525                      (p->p_agenttp != NULL &&
 529  526                      (t != p->p_agenttp || pnp->pr_type != PR_LWPIDFILE))) {
 530  527                          prunlock(pnp);
 531  528                          error = EBUSY;
 532  529                          break;
 533  530                  }
 534  531  
 535  532                  if (flags & (PRSHOLD|PRSTRACE|PRSFAULT|PRSVADDR))
 536  533                          prsetrun(t, &un.prrun);
 537  534  
 538  535                  error = pr_setrun(pnp, prmaprunflags(flags));
 539  536  
 540  537                  prunlock(pnp);
 541  538                  break;
 542  539          }
 543  540  
 544  541          case PIOCLWPIDS:        /* get array of lwp identifiers */
 545  542          {
 546  543                  int nlwp;
 547  544                  int Nlwp;
 548  545                  id_t *idp;
 549  546                  id_t *Bidp;
 550  547  
 551  548                  Nlwp = nlwp = p->p_lwpcnt;
 552  549  
 553  550                  if (thing && thingsize != (Nlwp+1) * sizeof (id_t)) {
 554  551                          kmem_free(thing, thingsize);
 555  552                          thing = NULL;
 556  553                  }
 557  554                  if (thing == NULL) {
 558  555                          thingsize = (Nlwp+1) * sizeof (id_t);
 559  556                          thing = kmem_alloc(thingsize, KM_NOSLEEP);
 560  557                  }
 561  558                  if (thing == NULL) {
 562  559                          prunlock(pnp);
 563  560                          goto startover;
 564  561                  }
 565  562  
 566  563                  idp = thing;
 567  564                  thing = NULL;
 568  565                  Bidp = idp;
 569  566                  if ((t = p->p_tlist) != NULL) {
 570  567                          do {
 571  568                                  ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
 572  569                                  ASSERT(nlwp > 0);
 573  570                                  --nlwp;
 574  571                                  *idp++ = t->t_tid;
 575  572                          } while ((t = t->t_forw) != p->p_tlist);
 576  573                  }
 577  574                  *idp = 0;
 578  575                  ASSERT(nlwp == 0);
 579  576                  prunlock(pnp);
 580  577                  if (copyout(Bidp, cmaddr, (Nlwp+1) * sizeof (id_t)))
 581  578                          error = EFAULT;
 582  579                  kmem_free(Bidp, (Nlwp+1) * sizeof (id_t));
 583  580                  break;
 584  581          }
 585  582  
 586  583          case PIOCOPENLWP:       /* return /proc lwp file descriptor */
 587  584          {
 588  585                  vnode_t *xvp;
 589  586                  int n;
 590  587  
 591  588                  prunlock(pnp);
 592  589                  if ((xvp = prlwpnode(pnp, un.lwpid)) == NULL)
 593  590                          error = ENOENT;
 594  591                  else if (error = fassign(&xvp, flag & (FREAD|FWRITE), &n)) {
 595  592                          VN_RELE(xvp);
 596  593                  } else
 597  594                          *rvalp = n;
 598  595                  break;
 599  596          }
 600  597  
 601  598          case PIOCOPENPD:        /* return /proc page data file descriptor */
 602  599          {
 603  600                  vnode_t *xvp = PTOV(xpnp);
 604  601                  vnode_t *dp = pnp->pr_parent;
 605  602                  int n;
 606  603  
 607  604                  if (pnp->pr_type == PR_LWPIDFILE) {
 608  605                          dp = VTOP(dp)->pr_parent;
 609  606                          dp = VTOP(dp)->pr_parent;
 610  607                  }
 611  608                  ASSERT(VTOP(dp)->pr_type == PR_PIDDIR);
 612  609  
 613  610                  VN_HOLD(dp);
 614  611                  pcp = pnp->pr_pcommon;
 615  612                  xpnp->pr_ino = ptoi(pcp->prc_pid);
 616  613                  xpnp->pr_common = pcp;
 617  614                  xpnp->pr_pcommon = pcp;
 618  615                  xpnp->pr_parent = dp;
 619  616  
 620  617                  xpnp->pr_next = p->p_plist;
 621  618                  p->p_plist = xvp;
 622  619  
 623  620                  prunlock(pnp);
 624  621                  if (error = fassign(&xvp, FREAD, &n)) {
 625  622                          VN_RELE(xvp);
 626  623                  } else
 627  624                          *rvalp = n;
 628  625  
 629  626                  xpnp = NULL;
 630  627                  break;
 631  628          }
 632  629  
 633  630          case PIOCGTRACE:        /* get signal trace mask */
 634  631                  prassignset(&un.smask, &p->p_sigmask);
 635  632                  prunlock(pnp);
 636  633                  if (copyout(&un.smask, cmaddr, sizeof (un.smask)))
 637  634                          error = EFAULT;
 638  635                  break;
 639  636  
 640  637          case PIOCSTRACE:        /* set signal trace mask */
 641  638                  prdelset(&un.smask, SIGKILL);
 642  639                  prassignset(&p->p_sigmask, &un.smask);
 643  640                  if (!sigisempty(&p->p_sigmask))
 644  641                          p->p_proc_flag |= P_PR_TRACE;
 645  642                  else if (prisempty(&p->p_fltmask)) {
 646  643                          up = PTOU(p);
 647  644                          if (up->u_systrap == 0)
 648  645                                  p->p_proc_flag &= ~P_PR_TRACE;
 649  646                  }
 650  647                  prunlock(pnp);
 651  648                  break;
 652  649  
 653  650          case PIOCSSIG:          /* set current signal */
 654  651                  error = pr_setsig(pnp, &un.info);
 655  652                  prunlock(pnp);
 656  653                  if (un.info.si_signo == SIGKILL && error == 0)
 657  654                          pr_wait_die(pnp);
 658  655                  break;
 659  656  
 660  657          case PIOCKILL:          /* send signal */
 661  658          {
 662  659                  int sig = (int)un.signo;
 663  660  
 664  661                  error = pr_kill(pnp, sig, cr);
 665  662                  prunlock(pnp);
 666  663                  if (sig == SIGKILL && error == 0)
 667  664                          pr_wait_die(pnp);
 668  665                  break;
 669  666          }
 670  667  
 671  668          case PIOCUNKILL:        /* delete a signal */
 672  669                  error = pr_unkill(pnp, (int)un.signo);
 673  670                  prunlock(pnp);
 674  671                  break;
 675  672  
 676  673          case PIOCNICE:          /* set nice priority */
 677  674                  error = pr_nice(p, (int)un.nice, cr);
 678  675                  prunlock(pnp);
 679  676                  break;
 680  677  
 681  678          case PIOCGENTRY:        /* get syscall entry bit mask */
 682  679          case PIOCGEXIT:         /* get syscall exit bit mask */
 683  680                  up = PTOU(p);
 684  681                  if (cmd == PIOCGENTRY) {
 685  682                          prassignset(&un.prmask, &up->u_entrymask);
 686  683                  } else {
 687  684                          prassignset(&un.prmask, &up->u_exitmask);
 688  685                  }
 689  686                  prunlock(pnp);
 690  687                  if (copyout(&un.prmask, cmaddr, sizeof (un.prmask)))
 691  688                          error = EFAULT;
 692  689                  break;
 693  690  
 694  691          case PIOCSENTRY:        /* set syscall entry bit mask */
 695  692          case PIOCSEXIT:         /* set syscall exit bit mask */
 696  693                  pr_setentryexit(p, &un.prmask, cmd == PIOCSENTRY);
 697  694                  prunlock(pnp);
 698  695                  break;
 699  696  
 700  697          case PIOCSRLC:          /* obsolete: set running on last /proc close */
 701  698                  error = pr_set(p, prmapsetflags(PR_RLC));
 702  699                  prunlock(pnp);
 703  700                  break;
 704  701  
 705  702          case PIOCRRLC:          /* obsolete: reset run-on-last-close flag */
 706  703                  error = pr_unset(p, prmapsetflags(PR_RLC));
 707  704                  prunlock(pnp);
 708  705                  break;
 709  706  
 710  707          case PIOCSFORK:         /* obsolete: set inherit-on-fork flag */
 711  708                  error = pr_set(p, prmapsetflags(PR_FORK));
 712  709                  prunlock(pnp);
 713  710                  break;
 714  711  
 715  712          case PIOCRFORK:         /* obsolete: reset inherit-on-fork flag */
 716  713                  error = pr_unset(p, prmapsetflags(PR_FORK));
 717  714                  prunlock(pnp);
 718  715                  break;
 719  716  
 720  717          case PIOCSET:           /* set process flags */
 721  718                  error = pr_set(p, prmapsetflags(un.flags));
 722  719                  prunlock(pnp);
 723  720                  break;
 724  721  
 725  722          case PIOCRESET:         /* reset process flags */
 726  723                  error = pr_unset(p, prmapsetflags(un.flags));
 727  724                  prunlock(pnp);
 728  725                  break;
 729  726  
 730  727          case PIOCGREG:          /* get general registers */
 731  728                  if (t->t_state != TS_STOPPED && !VSTOPPED(t))
 732  729                          bzero(un.regs, sizeof (un.regs));
 733  730                  else {
 734  731                          /* drop p_lock while touching the lwp's stack */
 735  732                          mutex_exit(&p->p_lock);
 736  733                          prgetprregs(lwp, un.regs);
 737  734                          mutex_enter(&p->p_lock);
 738  735                  }
 739  736                  prunlock(pnp);
 740  737                  if (copyout(un.regs, cmaddr, sizeof (un.regs)))
 741  738                          error = EFAULT;
 742  739                  break;
 743  740  
 744  741          case PIOCSREG:          /* set general registers */
 745  742                  if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
 746  743                          error = EBUSY;
 747  744                  else {
 748  745                          /* drop p_lock while touching the lwp's stack */
 749  746                          mutex_exit(&p->p_lock);
 750  747                          prsetprregs(lwp, un.regs, 0);
 751  748                          mutex_enter(&p->p_lock);
 752  749                  }
 753  750                  prunlock(pnp);
 754  751                  break;
 755  752  
 756  753          case PIOCGFPREG:        /* get floating-point registers */
 757  754                  if (!prhasfp()) {
 758  755                          prunlock(pnp);
 759  756                          error = EINVAL; /* No FP support */
 760  757                          break;
 761  758                  }
 762  759  
 763  760                  if (t->t_state != TS_STOPPED && !VSTOPPED(t))
 764  761                          bzero(&un.fpregs, sizeof (un.fpregs));
 765  762                  else {
 766  763                          /* drop p_lock while touching the lwp's stack */
 767  764                          mutex_exit(&p->p_lock);
 768  765                          prgetprfpregs(lwp, &un.fpregs);
 769  766                          mutex_enter(&p->p_lock);
 770  767                  }
 771  768                  prunlock(pnp);
 772  769                  if (copyout(&un.fpregs, cmaddr, sizeof (un.fpregs)))
 773  770                          error = EFAULT;
 774  771                  break;
 775  772  
 776  773          case PIOCSFPREG:        /* set floating-point registers */
 777  774                  if (!prhasfp())
 778  775                          error = EINVAL; /* No FP support */
 779  776                  else if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
 780  777                          error = EBUSY;
 781  778                  else {
  
    | 
      ↓ open down ↓ | 
    366 lines elided | 
    
      ↑ open up ↑ | 
  
 782  779                          /* drop p_lock while touching the lwp's stack */
 783  780                          mutex_exit(&p->p_lock);
 784  781                          prsetprfpregs(lwp, &un.fpregs);
 785  782                          mutex_enter(&p->p_lock);
 786  783                  }
 787  784                  prunlock(pnp);
 788  785                  break;
 789  786  
 790  787          case PIOCGXREGSIZE:     /* get the size of the extra registers */
 791  788          {
 792      -                int xregsize;
 793      -
 794  789                  if (prhasx(p)) {
      790 +                        size_t xregsize;
      791 +                        int abisize;
      792 +
 795  793                          xregsize = prgetprxregsize(p);
 796  794                          prunlock(pnp);
 797      -                        if (copyout(&xregsize, cmaddr, sizeof (xregsize)))
      795 +                        if (xregsize > INT_MAX) {
      796 +                                error = EOVERFLOW;
      797 +                                break;
      798 +                        }
      799 +
      800 +                        abisize = (int)xregsize;
      801 +                        if (copyout(&abisize, cmaddr, sizeof (abisize)))
 798  802                                  error = EFAULT;
 799  803                  } else {
 800  804                          prunlock(pnp);
 801  805                          error = EINVAL; /* No extra register support */
 802  806                  }
 803  807                  break;
 804  808          }
 805  809  
 806  810          case PIOCGXREG:         /* get extra registers */
 807  811                  if (prhasx(p)) {
 808  812                          bzero(thing, thingsize);
 809  813                          if (t->t_state == TS_STOPPED || VSTOPPED(t)) {
 810  814                                  /* drop p_lock to touch the stack */
 811  815                                  mutex_exit(&p->p_lock);
 812  816                                  prgetprxregs(lwp, thing);
 813  817                                  mutex_enter(&p->p_lock);
 814  818                          }
 815  819                          prunlock(pnp);
 816  820                          if (copyout(thing, cmaddr, thingsize))
 817  821                                  error = EFAULT;
  
    | 
      ↓ open down ↓ | 
    10 lines elided | 
    
      ↑ open up ↑ | 
  
 818  822                  } else {
 819  823                          prunlock(pnp);
 820  824                          error = EINVAL; /* No extra register support */
 821  825                  }
 822  826                  if (thing) {
 823  827                          kmem_free(thing, thingsize);
 824  828                          thing = NULL;
 825  829                  }
 826  830                  break;
 827  831  
 828      -        case PIOCSXREG:         /* set extra registers */
 829      -                if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
 830      -                        error = EBUSY;
 831      -                else if (!prhasx(p))
 832      -                        error = EINVAL; /* No extra register support */
 833      -                else if (thing) {
 834      -                        /* drop p_lock while touching the lwp's stack */
 835      -                        mutex_exit(&p->p_lock);
 836      -                        prsetprxregs(lwp, thing);
 837      -                        mutex_enter(&p->p_lock);
 838      -                }
 839      -                prunlock(pnp);
 840      -                if (thing) {
 841      -                        kmem_free(thing, thingsize);
 842      -                        thing = NULL;
 843      -                }
 844      -                break;
 845      -
 846  832          case PIOCSTATUS:        /* get process/lwp status */
 847  833                  oprgetstatus(t, &un.prstat, VTOZONE(vp));
 848  834                  prunlock(pnp);
 849  835                  if (copyout(&un.prstat, cmaddr, sizeof (un.prstat)))
 850  836                          error = EFAULT;
 851  837                  break;
 852  838  
 853  839          case PIOCLSTATUS:       /* get status for process & all lwps */
 854  840          {
 855  841                  int Nlwp;
 856  842                  int nlwp;
 857  843                  prstatus_t *Bprsp;
 858  844                  prstatus_t *prsp;
 859  845  
 860  846                  nlwp = Nlwp = p->p_lwpcnt;
 861  847  
 862  848                  if (thing && thingsize != (Nlwp+1) * sizeof (prstatus_t)) {
 863  849                          kmem_free(thing, thingsize);
 864  850                          thing = NULL;
 865  851                  }
 866  852                  if (thing == NULL) {
 867  853                          thingsize = (Nlwp+1) * sizeof (prstatus_t);
 868  854                          thing = kmem_alloc(thingsize, KM_NOSLEEP);
 869  855                  }
 870  856                  if (thing == NULL) {
 871  857                          prunlock(pnp);
 872  858                          goto startover;
 873  859                  }
 874  860  
 875  861                  Bprsp = thing;
 876  862                  thing = NULL;
 877  863                  prsp = Bprsp;
 878  864                  oprgetstatus(t, prsp, VTOZONE(vp));
 879  865                  t = p->p_tlist;
 880  866                  do {
 881  867                          ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
 882  868                          ASSERT(nlwp > 0);
 883  869                          --nlwp;
 884  870                          oprgetstatus(t, ++prsp, VTOZONE(vp));
 885  871                  } while ((t = t->t_forw) != p->p_tlist);
 886  872                  ASSERT(nlwp == 0);
 887  873                  prunlock(pnp);
 888  874                  if (copyout(Bprsp, cmaddr, (Nlwp+1) * sizeof (prstatus_t)))
 889  875                          error = EFAULT;
 890  876  
 891  877                  kmem_free(Bprsp, (Nlwp+1) * sizeof (prstatus_t));
 892  878                  break;
 893  879          }
 894  880  
 895  881          case PIOCPSINFO:        /* get ps(1) information */
 896  882          {
 897  883                  prpsinfo_t *psp = &un.prps;
 898  884  
 899  885                  oprgetpsinfo(p, psp,
 900  886                      (pnp->pr_type == PR_LWPIDFILE)? pcp->prc_thread : NULL);
 901  887  
 902  888                  prunlock(pnp);
 903  889                  if (copyout(&un.prps, cmaddr, sizeof (un.prps)))
 904  890                          error = EFAULT;
 905  891                  break;
 906  892          }
 907  893  
 908  894          case PIOCMAXSIG:        /* get maximum signal number */
 909  895          {
 910  896                  int n = nsig-1;
 911  897  
 912  898                  prunlock(pnp);
 913  899                  if (copyout(&n, cmaddr, sizeof (n)))
 914  900                          error = EFAULT;
 915  901                  break;
 916  902          }
 917  903  
 918  904          case PIOCACTION:        /* get signal action structures */
 919  905          {
 920  906                  uint_t sig;
 921  907                  struct sigaction *sap = thing;
 922  908  
 923  909                  up = PTOU(p);
 924  910                  for (sig = 1; sig < nsig; sig++)
 925  911                          prgetaction(p, up, sig, &sap[sig-1]);
 926  912                  prunlock(pnp);
 927  913                  if (copyout(sap, cmaddr, (nsig-1) * sizeof (struct sigaction)))
 928  914                          error = EFAULT;
 929  915                  kmem_free(sap, (nsig-1) * sizeof (struct sigaction));
 930  916                  thing = NULL;
 931  917                  break;
 932  918          }
 933  919  
 934  920          case PIOCGHOLD:         /* get signal-hold mask */
 935  921                  prgethold(t, &un.holdmask);
 936  922                  prunlock(pnp);
 937  923                  if (copyout(&un.holdmask, cmaddr, sizeof (un.holdmask)))
 938  924                          error = EFAULT;
 939  925                  break;
 940  926  
 941  927          case PIOCSHOLD:         /* set signal-hold mask */
 942  928                  pr_sethold(pnp, &un.holdmask);
 943  929                  prunlock(pnp);
 944  930                  break;
 945  931  
 946  932          case PIOCNMAP:          /* get number of memory mappings */
 947  933          {
 948  934                  uint_t n;
 949  935                  struct as *as = p->p_as;
 950  936  
 951  937                  if ((p->p_flag & SSYS) || as == &kas)
 952  938                          n = 0;
 953  939                  else {
 954  940                          mutex_exit(&p->p_lock);
 955  941                          AS_LOCK_ENTER(as, RW_WRITER);
 956  942                          n = prnsegs(as, 0);
 957  943                          AS_LOCK_EXIT(as);
 958  944                          mutex_enter(&p->p_lock);
 959  945                  }
 960  946                  prunlock(pnp);
 961  947                  if (copyout(&n, cmaddr, sizeof (uint_t)))
 962  948                          error = EFAULT;
 963  949                  break;
 964  950          }
 965  951  
 966  952          case PIOCMAP:           /* get memory map information */
 967  953          {
 968  954                  list_t iolhead;
 969  955                  struct as *as = p->p_as;
 970  956  
 971  957                  if ((p->p_flag & SSYS) || as == &kas) {
 972  958                          error = 0;
 973  959                          prunlock(pnp);
 974  960                  } else {
 975  961                          mutex_exit(&p->p_lock);
 976  962                          AS_LOCK_ENTER(as, RW_WRITER);
 977  963                          error = oprgetmap(p, &iolhead);
 978  964                          AS_LOCK_EXIT(as);
 979  965                          mutex_enter(&p->p_lock);
 980  966                          prunlock(pnp);
 981  967  
 982  968                          error = pr_iol_copyout_and_free(&iolhead,
 983  969                              &cmaddr, error);
 984  970                  }
 985  971                  /*
 986  972                   * The procfs PIOCMAP ioctl returns an all-zero buffer
 987  973                   * to indicate the end of the prmap[] array.
 988  974                   * Append it to whatever has already been copied out.
 989  975                   */
 990  976                  bzero(&un.prmap, sizeof (un.prmap));
 991  977                  if (!error && copyout(&un.prmap, cmaddr, sizeof (un.prmap)))
 992  978                          error = EFAULT;
 993  979  
 994  980                  break;
 995  981          }
 996  982  
 997  983          case PIOCGFAULT:        /* get mask of traced faults */
 998  984                  prassignset(&un.fltmask, &p->p_fltmask);
 999  985                  prunlock(pnp);
1000  986                  if (copyout(&un.fltmask, cmaddr, sizeof (un.fltmask)))
1001  987                          error = EFAULT;
1002  988                  break;
1003  989  
1004  990          case PIOCSFAULT:        /* set mask of traced faults */
1005  991                  pr_setfault(p, &un.fltmask);
1006  992                  prunlock(pnp);
1007  993                  break;
1008  994  
1009  995          case PIOCCFAULT:        /* clear current fault */
1010  996                  lwp->lwp_curflt = 0;
1011  997                  prunlock(pnp);
1012  998                  break;
1013  999  
1014 1000          case PIOCCRED:          /* get process credentials */
1015 1001          {
1016 1002                  cred_t *cp;
1017 1003  
1018 1004                  mutex_enter(&p->p_crlock);
1019 1005                  cp = p->p_cred;
1020 1006                  un.prcred.pr_euid = crgetuid(cp);
1021 1007                  un.prcred.pr_ruid = crgetruid(cp);
1022 1008                  un.prcred.pr_suid = crgetsuid(cp);
1023 1009                  un.prcred.pr_egid = crgetgid(cp);
1024 1010                  un.prcred.pr_rgid = crgetrgid(cp);
1025 1011                  un.prcred.pr_sgid = crgetsgid(cp);
1026 1012                  un.prcred.pr_ngroups = crgetngroups(cp);
1027 1013                  mutex_exit(&p->p_crlock);
1028 1014  
1029 1015                  prunlock(pnp);
1030 1016                  if (copyout(&un.prcred, cmaddr, sizeof (un.prcred)))
1031 1017                          error = EFAULT;
1032 1018                  break;
1033 1019          }
1034 1020  
1035 1021          case PIOCGROUPS:        /* get supplementary groups */
1036 1022          {
1037 1023                  cred_t *cp;
1038 1024  
1039 1025                  mutex_enter(&p->p_crlock);
1040 1026                  cp = p->p_cred;
1041 1027                  crhold(cp);
1042 1028                  mutex_exit(&p->p_crlock);
1043 1029  
1044 1030                  prunlock(pnp);
1045 1031                  if (copyout(crgetgroups(cp), cmaddr,
1046 1032                      MAX(crgetngroups(cp), 1) * sizeof (gid_t)))
1047 1033                          error = EFAULT;
1048 1034                  crfree(cp);
1049 1035                  break;
1050 1036          }
1051 1037  
1052 1038          case PIOCUSAGE:         /* get usage info */
1053 1039          {
1054 1040                  /*
1055 1041                   * For an lwp file descriptor, return just the lwp usage.
1056 1042                   * For a process file descriptor, return total usage,
1057 1043                   * all current lwps plus all defunct lwps.
1058 1044                   */
1059 1045                  prhusage_t *pup = &un.prhusage;
1060 1046                  prusage_t *upup;
1061 1047  
1062 1048                  bzero(pup, sizeof (*pup));
1063 1049                  pup->pr_tstamp = gethrtime();
1064 1050  
1065 1051                  if (pnp->pr_type == PR_LWPIDFILE) {
1066 1052                          t = pcp->prc_thread;
1067 1053                          if (t != NULL)
1068 1054                                  prgetusage(t, pup);
1069 1055                          else
1070 1056                                  error = ENOENT;
1071 1057                  } else {
1072 1058                          pup->pr_count  = p->p_defunct;
1073 1059                          pup->pr_create = p->p_mstart;
1074 1060                          pup->pr_term   = p->p_mterm;
1075 1061  
1076 1062                          pup->pr_rtime    = p->p_mlreal;
1077 1063                          pup->pr_utime    = p->p_acct[LMS_USER];
1078 1064                          pup->pr_stime    = p->p_acct[LMS_SYSTEM];
1079 1065                          pup->pr_ttime    = p->p_acct[LMS_TRAP];
1080 1066                          pup->pr_tftime   = p->p_acct[LMS_TFAULT];
1081 1067                          pup->pr_dftime   = p->p_acct[LMS_DFAULT];
1082 1068                          pup->pr_kftime   = p->p_acct[LMS_KFAULT];
1083 1069                          pup->pr_ltime    = p->p_acct[LMS_USER_LOCK];
1084 1070                          pup->pr_slptime  = p->p_acct[LMS_SLEEP];
1085 1071                          pup->pr_wtime    = p->p_acct[LMS_WAIT_CPU];
1086 1072                          pup->pr_stoptime = p->p_acct[LMS_STOPPED];
1087 1073  
1088 1074                          pup->pr_minf  = p->p_ru.minflt;
1089 1075                          pup->pr_majf  = p->p_ru.majflt;
1090 1076                          pup->pr_nswap = p->p_ru.nswap;
1091 1077                          pup->pr_inblk = p->p_ru.inblock;
1092 1078                          pup->pr_oublk = p->p_ru.oublock;
1093 1079                          pup->pr_msnd  = p->p_ru.msgsnd;
1094 1080                          pup->pr_mrcv  = p->p_ru.msgrcv;
1095 1081                          pup->pr_sigs  = p->p_ru.nsignals;
1096 1082                          pup->pr_vctx  = p->p_ru.nvcsw;
1097 1083                          pup->pr_ictx  = p->p_ru.nivcsw;
1098 1084                          pup->pr_sysc  = p->p_ru.sysc;
1099 1085                          pup->pr_ioch  = p->p_ru.ioch;
1100 1086  
1101 1087                          /*
1102 1088                           * Add the usage information for each active lwp.
1103 1089                           */
1104 1090                          if ((t = p->p_tlist) != NULL &&
1105 1091                              !(pcp->prc_flags & PRC_DESTROY)) {
1106 1092                                  do {
1107 1093                                          ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
1108 1094                                          pup->pr_count++;
1109 1095                                          praddusage(t, pup);
1110 1096                                  } while ((t = t->t_forw) != p->p_tlist);
1111 1097                          }
1112 1098                  }
1113 1099  
1114 1100                  prunlock(pnp);
1115 1101  
1116 1102                  upup = kmem_zalloc(sizeof (*upup), KM_SLEEP);
1117 1103                  prcvtusage(&un.prhusage, upup);
1118 1104                  if (copyout(upup, cmaddr, sizeof (*upup)))
1119 1105                          error = EFAULT;
1120 1106                  kmem_free(upup, sizeof (*upup));
1121 1107  
1122 1108                  break;
1123 1109          }
1124 1110  
1125 1111          case PIOCLUSAGE:        /* get detailed usage info */
1126 1112          {
1127 1113                  int Nlwp;
1128 1114                  int nlwp;
1129 1115                  prusage_t *upup;
1130 1116                  prusage_t *Bupup;
1131 1117                  prhusage_t *pup;
1132 1118                  hrtime_t curtime;
1133 1119  
1134 1120                  nlwp = Nlwp = (pcp->prc_flags & PRC_DESTROY)? 0 : p->p_lwpcnt;
1135 1121  
1136 1122                  if (thing && thingsize !=
1137 1123                      sizeof (prhusage_t) + (Nlwp+1) * sizeof (prusage_t)) {
1138 1124                          kmem_free(thing, thingsize);
1139 1125                          thing = NULL;
1140 1126                  }
1141 1127                  if (thing == NULL) {
1142 1128                          thingsize = sizeof (prhusage_t) +
1143 1129                              (Nlwp+1) * sizeof (prusage_t);
1144 1130                          thing = kmem_alloc(thingsize, KM_NOSLEEP);
1145 1131                  }
1146 1132                  if (thing == NULL) {
1147 1133                          prunlock(pnp);
1148 1134                          goto startover;
1149 1135                  }
1150 1136  
1151 1137                  pup = thing;
1152 1138                  upup = Bupup = (prusage_t *)(pup + 1);
1153 1139  
1154 1140                  ASSERT(p == pcp->prc_proc);
1155 1141  
1156 1142                  curtime = gethrtime();
1157 1143  
1158 1144                  /*
1159 1145                   * First the summation over defunct lwps.
1160 1146                   */
1161 1147                  bzero(pup, sizeof (*pup));
1162 1148                  pup->pr_count  = p->p_defunct;
1163 1149                  pup->pr_tstamp = curtime;
1164 1150                  pup->pr_create = p->p_mstart;
1165 1151                  pup->pr_term   = p->p_mterm;
1166 1152  
1167 1153                  pup->pr_rtime    = p->p_mlreal;
1168 1154                  pup->pr_utime    = p->p_acct[LMS_USER];
1169 1155                  pup->pr_stime    = p->p_acct[LMS_SYSTEM];
1170 1156                  pup->pr_ttime    = p->p_acct[LMS_TRAP];
1171 1157                  pup->pr_tftime   = p->p_acct[LMS_TFAULT];
1172 1158                  pup->pr_dftime   = p->p_acct[LMS_DFAULT];
1173 1159                  pup->pr_kftime   = p->p_acct[LMS_KFAULT];
1174 1160                  pup->pr_ltime    = p->p_acct[LMS_USER_LOCK];
1175 1161                  pup->pr_slptime  = p->p_acct[LMS_SLEEP];
1176 1162                  pup->pr_wtime    = p->p_acct[LMS_WAIT_CPU];
1177 1163                  pup->pr_stoptime = p->p_acct[LMS_STOPPED];
1178 1164  
1179 1165                  pup->pr_minf  = p->p_ru.minflt;
1180 1166                  pup->pr_majf  = p->p_ru.majflt;
1181 1167                  pup->pr_nswap = p->p_ru.nswap;
1182 1168                  pup->pr_inblk = p->p_ru.inblock;
1183 1169                  pup->pr_oublk = p->p_ru.oublock;
1184 1170                  pup->pr_msnd  = p->p_ru.msgsnd;
1185 1171                  pup->pr_mrcv  = p->p_ru.msgrcv;
1186 1172                  pup->pr_sigs  = p->p_ru.nsignals;
1187 1173                  pup->pr_vctx  = p->p_ru.nvcsw;
1188 1174                  pup->pr_ictx  = p->p_ru.nivcsw;
1189 1175                  pup->pr_sysc  = p->p_ru.sysc;
1190 1176                  pup->pr_ioch  = p->p_ru.ioch;
1191 1177  
1192 1178                  prcvtusage(pup, upup);
1193 1179  
1194 1180                  /*
1195 1181                   * Fill one prusage struct for each active lwp.
1196 1182                   */
1197 1183                  if ((t = p->p_tlist) != NULL &&
1198 1184                      !(pcp->prc_flags & PRC_DESTROY)) {
1199 1185                          do {
1200 1186                                  ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
1201 1187                                  ASSERT(nlwp > 0);
1202 1188                                  --nlwp;
1203 1189                                  upup++;
1204 1190                                  prgetusage(t, pup);
1205 1191                                  prcvtusage(pup, upup);
1206 1192                          } while ((t = t->t_forw) != p->p_tlist);
1207 1193                  }
1208 1194                  ASSERT(nlwp == 0);
1209 1195  
1210 1196                  prunlock(pnp);
1211 1197                  if (copyout(Bupup, cmaddr, (Nlwp+1) * sizeof (prusage_t)))
1212 1198                          error = EFAULT;
1213 1199                  kmem_free(thing, thingsize);
1214 1200                  thing = NULL;
1215 1201                  break;
1216 1202          }
1217 1203  
1218 1204          case PIOCNAUXV:         /* get number of aux vector entries */
1219 1205          {
1220 1206                  int n = __KERN_NAUXV_IMPL;
1221 1207  
1222 1208                  prunlock(pnp);
1223 1209                  if (copyout(&n, cmaddr, sizeof (int)))
1224 1210                          error = EFAULT;
1225 1211                  break;
1226 1212          }
1227 1213  
1228 1214          case PIOCAUXV:          /* get aux vector (see sys/auxv.h) */
1229 1215          {
1230 1216                  up = PTOU(p);
1231 1217                  bcopy(up->u_auxv, un.auxv,
1232 1218                      __KERN_NAUXV_IMPL * sizeof (auxv_t));
1233 1219                  prunlock(pnp);
1234 1220                  if (copyout(un.auxv, cmaddr,
1235 1221                      __KERN_NAUXV_IMPL * sizeof (auxv_t)))
1236 1222                          error = EFAULT;
1237 1223                  break;
1238 1224          }
1239 1225  
1240 1226  #if defined(__x86)
1241 1227          case PIOCNLDT:          /* get number of LDT entries */
1242 1228          {
1243 1229                  int n;
1244 1230  
1245 1231                  mutex_exit(&p->p_lock);
1246 1232                  mutex_enter(&p->p_ldtlock);
1247 1233                  n = prnldt(p);
1248 1234                  mutex_exit(&p->p_ldtlock);
1249 1235                  mutex_enter(&p->p_lock);
1250 1236                  prunlock(pnp);
1251 1237                  if (copyout(&n, cmaddr, sizeof (n)))
1252 1238                          error = EFAULT;
1253 1239                  break;
1254 1240          }
1255 1241  
1256 1242          case PIOCLDT:           /* get LDT entries */
1257 1243          {
1258 1244                  struct ssd *ssd;
1259 1245                  int n;
1260 1246  
1261 1247                  mutex_exit(&p->p_lock);
1262 1248                  mutex_enter(&p->p_ldtlock);
1263 1249                  n = prnldt(p);
1264 1250  
1265 1251                  if (thing && thingsize != (n+1) * sizeof (*ssd)) {
1266 1252                          kmem_free(thing, thingsize);
1267 1253                          thing = NULL;
1268 1254                  }
1269 1255                  if (thing == NULL) {
1270 1256                          thingsize = (n+1) * sizeof (*ssd);
1271 1257                          thing = kmem_alloc(thingsize, KM_NOSLEEP);
1272 1258                  }
1273 1259                  if (thing == NULL) {
1274 1260                          mutex_exit(&p->p_ldtlock);
1275 1261                          mutex_enter(&p->p_lock);
1276 1262                          prunlock(pnp);
1277 1263                          goto startover;
1278 1264                  }
1279 1265  
1280 1266                  ssd = thing;
1281 1267                  thing = NULL;
1282 1268                  if (n != 0)
1283 1269                          prgetldt(p, ssd);
1284 1270                  mutex_exit(&p->p_ldtlock);
1285 1271                  mutex_enter(&p->p_lock);
1286 1272                  prunlock(pnp);
1287 1273  
1288 1274                  /* mark the end of the list with a null entry */
1289 1275                  bzero(&ssd[n], sizeof (*ssd));
1290 1276                  if (copyout(ssd, cmaddr, (n+1) * sizeof (*ssd)))
1291 1277                          error = EFAULT;
1292 1278                  kmem_free(ssd, (n+1) * sizeof (*ssd));
1293 1279                  break;
1294 1280          }
1295 1281  #endif  /* __x86 */
1296 1282  
1297 1283  #if defined(__sparc)
1298 1284          case PIOCGWIN:          /* get gwindows_t (see sys/reg.h) */
1299 1285          {
1300 1286                  gwindows_t *gwp = thing;
1301 1287  
1302 1288                  /* drop p->p_lock while touching the stack */
1303 1289                  mutex_exit(&p->p_lock);
1304 1290                  bzero(gwp, sizeof (*gwp));
1305 1291                  prgetwindows(lwp, gwp);
1306 1292                  mutex_enter(&p->p_lock);
1307 1293                  prunlock(pnp);
1308 1294                  if (copyout(gwp, cmaddr, sizeof (*gwp)))
1309 1295                          error = EFAULT;
1310 1296                  kmem_free(gwp, sizeof (gwindows_t));
1311 1297                  thing = NULL;
1312 1298                  break;
1313 1299          }
1314 1300  #endif  /* __sparc */
1315 1301  
1316 1302          default:
1317 1303                  prunlock(pnp);
1318 1304                  error = EINVAL;
1319 1305                  break;
1320 1306  
1321 1307          }
1322 1308  
1323 1309          ASSERT(thing == NULL);
1324 1310          ASSERT(xpnp == NULL);
1325 1311          return (error);
1326 1312  }
1327 1313  
1328 1314  #ifdef _SYSCALL32_IMPL
1329 1315  
1330 1316  static int oprgetmap32(proc_t *, list_t *);
1331 1317  
1332 1318  void
1333 1319  oprgetstatus32(kthread_t *t, prstatus32_t *sp, zone_t *zp)
1334 1320  {
1335 1321          proc_t *p = ttoproc(t);
1336 1322          klwp_t *lwp = ttolwp(t);
1337 1323          int32_t flags;
1338 1324          user_t *up;
1339 1325          ulong_t instr;
1340 1326  
1341 1327          ASSERT(MUTEX_HELD(&p->p_lock));
1342 1328  
1343 1329          up = PTOU(p);
1344 1330          bzero(sp, sizeof (*sp));
1345 1331          flags = 0L;
1346 1332          if (t->t_state == TS_STOPPED) {
1347 1333                  flags |= PR_STOPPED;
1348 1334                  if ((t->t_schedflag & TS_PSTART) == 0)
1349 1335                          flags |= PR_ISTOP;
1350 1336          } else if (VSTOPPED(t)) {
1351 1337                  flags |= PR_STOPPED|PR_ISTOP;
1352 1338          }
1353 1339          if (!(flags & PR_ISTOP) && (t->t_proc_flag & TP_PRSTOP))
1354 1340                  flags |= PR_DSTOP;
1355 1341          if (lwp->lwp_asleep)
1356 1342                  flags |= PR_ASLEEP;
1357 1343          if (p->p_proc_flag & P_PR_FORK)
1358 1344                  flags |= PR_FORK;
1359 1345          if (p->p_proc_flag & P_PR_RUNLCL)
1360 1346                  flags |= PR_RLC;
1361 1347          if (p->p_proc_flag & P_PR_KILLCL)
1362 1348                  flags |= PR_KLC;
1363 1349          if (p->p_proc_flag & P_PR_ASYNC)
1364 1350                  flags |= PR_ASYNC;
1365 1351          if (p->p_proc_flag & P_PR_BPTADJ)
1366 1352                  flags |= PR_BPTADJ;
1367 1353          if (p->p_proc_flag & P_PR_PTRACE)
1368 1354                  flags |= PR_PCOMPAT;
1369 1355          if (t->t_proc_flag & TP_MSACCT)
1370 1356                  flags |= PR_MSACCT;
1371 1357          sp->pr_flags = flags;
1372 1358          if (VSTOPPED(t)) {
1373 1359                  sp->pr_why   = PR_REQUESTED;
1374 1360                  sp->pr_what  = 0;
1375 1361          } else {
1376 1362                  sp->pr_why   = t->t_whystop;
1377 1363                  sp->pr_what  = t->t_whatstop;
1378 1364          }
1379 1365  
1380 1366          if (t->t_whystop == PR_FAULTED) {
1381 1367                  siginfo_kto32(&lwp->lwp_siginfo, &sp->pr_info);
1382 1368                  if (t->t_whatstop == FLTPAGE)
1383 1369                          sp->pr_info.si_addr =
1384 1370                              (caddr32_t)(uintptr_t)lwp->lwp_siginfo.si_addr;
1385 1371          } else if (lwp->lwp_curinfo)
1386 1372                  siginfo_kto32(&lwp->lwp_curinfo->sq_info, &sp->pr_info);
1387 1373  
1388 1374          if (SI_FROMUSER(&lwp->lwp_siginfo) && zp->zone_id != GLOBAL_ZONEID &&
1389 1375              sp->pr_info.si_zoneid != zp->zone_id) {
1390 1376                  sp->pr_info.si_pid = zp->zone_zsched->p_pid;
1391 1377                  sp->pr_info.si_uid = 0;
1392 1378                  sp->pr_info.si_ctid = -1;
1393 1379                  sp->pr_info.si_zoneid = zp->zone_id;
1394 1380          }
1395 1381  
1396 1382          sp->pr_cursig  = lwp->lwp_cursig;
1397 1383          prassignset(&sp->pr_sigpend, &p->p_sig);
1398 1384          prassignset(&sp->pr_lwppend, &t->t_sig);
1399 1385          prgethold(t, &sp->pr_sighold);
1400 1386          sp->pr_altstack.ss_sp =
1401 1387              (caddr32_t)(uintptr_t)lwp->lwp_sigaltstack.ss_sp;
1402 1388          sp->pr_altstack.ss_size = (size32_t)lwp->lwp_sigaltstack.ss_size;
1403 1389          sp->pr_altstack.ss_flags = (int32_t)lwp->lwp_sigaltstack.ss_flags;
1404 1390          prgetaction32(p, up, lwp->lwp_cursig, &sp->pr_action);
1405 1391          sp->pr_pid   = p->p_pid;
1406 1392          if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
1407 1393              (p->p_flag & SZONETOP)) {
1408 1394                  ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
1409 1395                  /*
1410 1396                   * Inside local zones, fake zsched's pid as parent pids for
1411 1397                   * processes which reference processes outside of the zone.
1412 1398                   */
1413 1399                  sp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
1414 1400          } else {
1415 1401                  sp->pr_ppid = p->p_ppid;
1416 1402          }
1417 1403          sp->pr_pgrp  = p->p_pgrp;
1418 1404          sp->pr_sid   = p->p_sessp->s_sid;
1419 1405          hrt2ts32(mstate_aggr_state(p, LMS_USER), &sp->pr_utime);
1420 1406          hrt2ts32(mstate_aggr_state(p, LMS_SYSTEM), &sp->pr_stime);
1421 1407          TICK_TO_TIMESTRUC32(p->p_cutime, &sp->pr_cutime);
1422 1408          TICK_TO_TIMESTRUC32(p->p_cstime, &sp->pr_cstime);
1423 1409          (void) strncpy(sp->pr_clname, sclass[t->t_cid].cl_name,
1424 1410              sizeof (sp->pr_clname) - 1);
1425 1411          sp->pr_who = t->t_tid;
1426 1412          sp->pr_nlwp = p->p_lwpcnt;
1427 1413          sp->pr_brkbase = (caddr32_t)(uintptr_t)p->p_brkbase;
1428 1414          sp->pr_brksize = (size32_t)p->p_brksize;
1429 1415          sp->pr_stkbase = (caddr32_t)(uintptr_t)prgetstackbase(p);
1430 1416          sp->pr_stksize = (size32_t)p->p_stksize;
1431 1417          sp->pr_oldcontext = (caddr32_t)lwp->lwp_oldcontext;
1432 1418          sp->pr_processor = t->t_cpu->cpu_id;
1433 1419          sp->pr_bind = t->t_bind_cpu;
1434 1420  
1435 1421          /*
1436 1422           * Fetch the current instruction, if not a system process.
1437 1423           * We don't attempt this unless the lwp is stopped.
1438 1424           */
1439 1425          if ((p->p_flag & SSYS) || p->p_as == &kas)
1440 1426                  sp->pr_flags |= (PR_ISSYS|PR_PCINVAL);
1441 1427          else if (!(flags & PR_STOPPED))
1442 1428                  sp->pr_flags |= PR_PCINVAL;
1443 1429          else if (!prfetchinstr(lwp, &instr))
1444 1430                  sp->pr_flags |= PR_PCINVAL;
1445 1431          else
1446 1432                  sp->pr_instr = (uint32_t)instr;
1447 1433  
1448 1434          /*
1449 1435           * Drop p_lock while touching the lwp's stack.
1450 1436           */
1451 1437          mutex_exit(&p->p_lock);
1452 1438          if (prisstep(lwp))
1453 1439                  sp->pr_flags |= PR_STEP;
1454 1440          if ((flags & (PR_STOPPED|PR_ASLEEP)) && t->t_sysnum) {
1455 1441                  int i;
1456 1442                  auxv_t *auxp;
1457 1443  
1458 1444                  sp->pr_syscall = get_syscall32_args(lwp,
1459 1445                      (int *)sp->pr_sysarg, &i);
1460 1446                  sp->pr_nsysarg = (short)i;
1461 1447                  if (t->t_whystop == PR_SYSEXIT && t->t_sysnum == SYS_execve) {
1462 1448                          sp->pr_sysarg[0] = 0;
1463 1449                          sp->pr_sysarg[1] = (caddr32_t)up->u_argv;
1464 1450                          sp->pr_sysarg[2] = (caddr32_t)up->u_envp;
1465 1451                          for (i = 0, auxp = up->u_auxv;
1466 1452                              i < sizeof (up->u_auxv) / sizeof (up->u_auxv[0]);
1467 1453                              i++, auxp++) {
1468 1454                                  if (auxp->a_type == AT_SUN_EXECNAME) {
1469 1455                                          sp->pr_sysarg[0] =
1470 1456                                              (caddr32_t)
1471 1457                                              (uintptr_t)auxp->a_un.a_ptr;
1472 1458                                          break;
1473 1459                                  }
1474 1460                          }
1475 1461                  }
1476 1462          }
1477 1463          if ((flags & PR_STOPPED) || t == curthread)
1478 1464                  prgetprregs32(lwp, sp->pr_reg);
1479 1465          mutex_enter(&p->p_lock);
1480 1466  }
1481 1467  
1482 1468  void
1483 1469  oprgetpsinfo32(proc_t *p, prpsinfo32_t *psp, kthread_t *tp)
1484 1470  {
1485 1471          kthread_t *t;
1486 1472          char c, state;
1487 1473          user_t *up;
1488 1474          dev_t d;
1489 1475          uint64_t pct;
1490 1476          int retval, niceval;
1491 1477          cred_t *cred;
1492 1478          struct as *as;
1493 1479          hrtime_t hrutime, hrstime, cur_time;
1494 1480  
1495 1481          ASSERT(MUTEX_HELD(&p->p_lock));
1496 1482  
1497 1483          bzero(psp, sizeof (*psp));
1498 1484  
1499 1485          if ((t = tp) == NULL)
1500 1486                  t = prchoose(p);        /* returns locked thread */
1501 1487          else
1502 1488                  thread_lock(t);
1503 1489  
1504 1490          /* kludge: map thread state enum into process state enum */
1505 1491  
1506 1492          if (t == NULL) {
1507 1493                  state = TS_ZOMB;
1508 1494          } else {
1509 1495                  state = VSTOPPED(t) ? TS_STOPPED : t->t_state;
1510 1496                  thread_unlock(t);
1511 1497          }
1512 1498  
1513 1499          switch (state) {
1514 1500          case TS_SLEEP:          state = SSLEEP;         break;
1515 1501          case TS_RUN:            state = SRUN;           break;
1516 1502          case TS_ONPROC:         state = SONPROC;        break;
1517 1503          case TS_ZOMB:           state = SZOMB;          break;
1518 1504          case TS_STOPPED:        state = SSTOP;          break;
1519 1505          default:                state = 0;              break;
1520 1506          }
1521 1507          switch (state) {
1522 1508          case SSLEEP:    c = 'S';        break;
1523 1509          case SRUN:      c = 'R';        break;
1524 1510          case SZOMB:     c = 'Z';        break;
1525 1511          case SSTOP:     c = 'T';        break;
1526 1512          case SIDL:      c = 'I';        break;
1527 1513          case SONPROC:   c = 'O';        break;
1528 1514  #ifdef SXBRK
1529 1515          case SXBRK:     c = 'X';        break;
1530 1516  #endif
1531 1517          default:        c = '?';        break;
1532 1518          }
1533 1519          psp->pr_state = state;
1534 1520          psp->pr_sname = c;
1535 1521          psp->pr_zomb = (state == SZOMB);
1536 1522          /*
1537 1523           * only export SSYS and SMSACCT; everything else is off-limits to
1538 1524           * userland apps.
1539 1525           */
1540 1526          psp->pr_flag = p->p_flag & (SSYS | SMSACCT);
1541 1527  
1542 1528          mutex_enter(&p->p_crlock);
1543 1529          cred = p->p_cred;
1544 1530          psp->pr_uid = crgetruid(cred);
1545 1531          psp->pr_gid = crgetrgid(cred);
1546 1532          psp->pr_euid = crgetuid(cred);
1547 1533          psp->pr_egid = crgetgid(cred);
1548 1534          mutex_exit(&p->p_crlock);
1549 1535  
1550 1536          psp->pr_pid = p->p_pid;
1551 1537          if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
1552 1538              (p->p_flag & SZONETOP)) {
1553 1539                  ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
1554 1540                  /*
1555 1541                   * Inside local zones, fake zsched's pid as parent pids for
1556 1542                   * processes which reference processes outside of the zone.
1557 1543                   */
1558 1544                  psp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
1559 1545          } else {
1560 1546                  psp->pr_ppid = p->p_ppid;
1561 1547          }
1562 1548          psp->pr_pgrp = p->p_pgrp;
1563 1549          psp->pr_sid = p->p_sessp->s_sid;
1564 1550          psp->pr_addr = 0;       /* cannot represent 64-bit addr in 32 bits */
1565 1551          hrutime = mstate_aggr_state(p, LMS_USER);
1566 1552          hrstime = mstate_aggr_state(p, LMS_SYSTEM);
1567 1553          hrt2ts32(hrutime + hrstime, &psp->pr_time);
1568 1554          TICK_TO_TIMESTRUC32(p->p_cutime + p->p_cstime, &psp->pr_ctime);
1569 1555          switch (p->p_model) {
1570 1556          case DATAMODEL_ILP32:
1571 1557                  psp->pr_dmodel = PR_MODEL_ILP32;
1572 1558                  break;
1573 1559          case DATAMODEL_LP64:
1574 1560                  psp->pr_dmodel = PR_MODEL_LP64;
1575 1561                  break;
1576 1562          }
1577 1563          if (state == SZOMB || t == NULL) {
1578 1564                  int wcode = p->p_wcode;         /* must be atomic read */
1579 1565  
1580 1566                  if (wcode)
1581 1567                          psp->pr_wstat = wstat(wcode, p->p_wdata);
1582 1568                  psp->pr_lttydev = PRNODEV32;
1583 1569                  psp->pr_ottydev = (o_dev_t)PRNODEV32;
1584 1570                  psp->pr_size = 0;
1585 1571                  psp->pr_rssize = 0;
1586 1572                  psp->pr_pctmem = 0;
1587 1573          } else {
1588 1574                  up = PTOU(p);
1589 1575                  psp->pr_wchan = 0;      /* cannot represent in 32 bits */
1590 1576                  psp->pr_pri = t->t_pri;
1591 1577                  (void) strncpy(psp->pr_clname, sclass[t->t_cid].cl_name,
1592 1578                      sizeof (psp->pr_clname) - 1);
1593 1579                  retval = CL_DONICE(t, NULL, 0, &niceval);
1594 1580                  if (retval == 0) {
1595 1581                          psp->pr_oldpri = v.v_maxsyspri - psp->pr_pri;
1596 1582                          psp->pr_nice = niceval + NZERO;
1597 1583                  } else {
1598 1584                          psp->pr_oldpri = 0;
1599 1585                          psp->pr_nice = 0;
1600 1586                  }
1601 1587                  d = cttydev(p);
1602 1588  #ifdef sun
1603 1589                  {
1604 1590                          extern dev_t rwsconsdev, rconsdev, uconsdev;
1605 1591                          /*
1606 1592                           * If the controlling terminal is the real
1607 1593                           * or workstation console device, map to what the
1608 1594                           * user thinks is the console device. Handle case when
1609 1595                           * rwsconsdev or rconsdev is set to NODEV for Starfire.
1610 1596                           */
1611 1597                          if ((d == rwsconsdev || d == rconsdev) && d != NODEV)
1612 1598                                  d = uconsdev;
1613 1599                  }
1614 1600  #endif
1615 1601                  (void) cmpldev(&psp->pr_lttydev, d);
1616 1602                  psp->pr_ottydev = cmpdev(d);
1617 1603                  TIMESPEC_TO_TIMESPEC32(&psp->pr_start, &up->u_start);
1618 1604                  bcopy(up->u_comm, psp->pr_fname,
1619 1605                      MIN(sizeof (up->u_comm), sizeof (psp->pr_fname)-1));
1620 1606                  bcopy(up->u_psargs, psp->pr_psargs,
1621 1607                      MIN(PRARGSZ-1, PSARGSZ));
1622 1608                  psp->pr_syscall = t->t_sysnum;
1623 1609                  psp->pr_argc = up->u_argc;
1624 1610                  psp->pr_argv = (caddr32_t)up->u_argv;
1625 1611                  psp->pr_envp = (caddr32_t)up->u_envp;
1626 1612  
1627 1613                  /* compute %cpu for the lwp or process */
1628 1614                  pct = 0;
1629 1615                  if ((t = tp) == NULL)
1630 1616                          t = p->p_tlist;
1631 1617                  cur_time = gethrtime_unscaled();
1632 1618                  do {
1633 1619                          pct += cpu_update_pct(t, cur_time);
1634 1620                          if (tp != NULL)         /* just do the one lwp */
1635 1621                                  break;
1636 1622                  } while ((t = t->t_forw) != p->p_tlist);
1637 1623  
1638 1624                  psp->pr_pctcpu = prgetpctcpu(pct);
1639 1625                  psp->pr_cpu = (psp->pr_pctcpu*100 + 0x6000) >> 15; /* [0..99] */
1640 1626                  if (psp->pr_cpu > 99)
1641 1627                          psp->pr_cpu = 99;
1642 1628  
1643 1629                  if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
1644 1630                          psp->pr_size = 0;
1645 1631                          psp->pr_rssize = 0;
1646 1632                          psp->pr_pctmem = 0;
1647 1633                  } else {
1648 1634                          mutex_exit(&p->p_lock);
1649 1635                          AS_LOCK_ENTER(as, RW_READER);
1650 1636                          psp->pr_size = (size32_t)btopr(as->a_resvsize);
1651 1637                          psp->pr_rssize = (size32_t)rm_asrss(as);
1652 1638                          psp->pr_pctmem = rm_pctmemory(as);
1653 1639                          AS_LOCK_EXIT(as);
1654 1640                          mutex_enter(&p->p_lock);
1655 1641                  }
1656 1642          }
1657 1643          psp->pr_bysize = (size32_t)ptob(psp->pr_size);
1658 1644          psp->pr_byrssize = (size32_t)ptob(psp->pr_rssize);
1659 1645  
1660 1646          /*
1661 1647           * If we are looking at an LP64 process, zero out
1662 1648           * the fields that cannot be represented in ILP32.
1663 1649           */
1664 1650          if (p->p_model != DATAMODEL_ILP32) {
1665 1651                  psp->pr_size = 0;
1666 1652                  psp->pr_rssize = 0;
1667 1653                  psp->pr_bysize = 0;
1668 1654                  psp->pr_byrssize = 0;
1669 1655                  psp->pr_argv = 0;
1670 1656                  psp->pr_envp = 0;
1671 1657          }
1672 1658  }
1673 1659  
1674 1660  /*ARGSUSED*/
1675 1661  static int
1676 1662  prioctl32(struct vnode *vp, int cmd, intptr_t arg, int flag, cred_t *cr,
1677 1663      int *rvalp, caller_context_t *ct)
1678 1664  {
1679 1665          int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG;
1680 1666          caddr_t cmaddr = (caddr_t)arg;
1681 1667          proc_t *p;
1682 1668          user_t *up;
1683 1669          kthread_t *t;
1684 1670          klwp_t *lwp;
1685 1671          prnode_t *pnp = VTOP(vp);
1686 1672          prcommon_t *pcp;
1687 1673          prnode_t *xpnp = NULL;
1688 1674          int error;
1689 1675          int zdisp;
1690 1676          void *thing = NULL;
1691 1677          size_t thingsize = 0;
1692 1678  
1693 1679          /*
1694 1680           * For copyin()/copyout().
1695 1681           */
1696 1682          union {
1697 1683                  caddr32_t       va;
1698 1684                  int             signo;
1699 1685                  int             nice;
1700 1686                  uint_t          lwpid;
1701 1687                  int32_t         flags;
1702 1688                  prstatus32_t    prstat;
1703 1689                  prrun32_t       prrun;
1704 1690                  sigset_t        smask;
1705 1691                  siginfo32_t     info;
1706 1692                  sysset_t        prmask;
1707 1693                  prgregset32_t   regs;
1708 1694                  prfpregset32_t  fpregs;
1709 1695                  prpsinfo32_t    prps;
1710 1696                  sigset_t        holdmask;
1711 1697                  fltset_t        fltmask;
1712 1698                  prcred_t        prcred;
1713 1699                  prusage32_t     prusage;
1714 1700                  prhusage_t      prhusage;
1715 1701                  ioc_prmap32_t   prmap;
1716 1702                  auxv32_t        auxv[__KERN_NAUXV_IMPL];
1717 1703          } un32;
1718 1704  
1719 1705          /*
1720 1706           * Native objects for internal use.
1721 1707           */
1722 1708          union {
1723 1709                  caddr_t         va;
1724 1710                  int             signo;
1725 1711                  int             nice;
1726 1712                  uint_t          lwpid;
1727 1713                  long            flags;
1728 1714                  prstatus_t      prstat;
1729 1715                  prrun_t         prrun;
1730 1716                  sigset_t        smask;
1731 1717                  siginfo_t       info;
1732 1718                  sysset_t        prmask;
1733 1719                  prgregset_t     regs;
1734 1720                  prpsinfo_t      prps;
1735 1721                  sigset_t        holdmask;
1736 1722                  fltset_t        fltmask;
1737 1723                  prcred_t        prcred;
1738 1724                  prusage_t       prusage;
1739 1725                  prhusage_t      prhusage;
1740 1726                  auxv_t          auxv[__KERN_NAUXV_IMPL];
1741 1727          } un;
1742 1728  
1743 1729          if (pnp->pr_type == PR_TMPL)
1744 1730                  return (prctioctl(pnp, cmd, arg, flag, cr));
1745 1731  
1746 1732          /*
1747 1733           * Support for old /proc interface.
1748 1734           */
1749 1735          if (pnp->pr_pidfile != NULL) {
1750 1736                  ASSERT(pnp->pr_type == PR_PIDDIR);
1751 1737                  vp = pnp->pr_pidfile;
1752 1738                  pnp = VTOP(vp);
1753 1739                  ASSERT(pnp->pr_type == PR_PIDFILE);
1754 1740          }
1755 1741  
1756 1742          if (pnp->pr_type != PR_PIDFILE && pnp->pr_type != PR_LWPIDFILE)
  
    | 
      ↓ open down ↓ | 
    901 lines elided | 
    
      ↑ open up ↑ | 
  
1757 1743                  return (ENOTTY);
1758 1744  
1759 1745          /*
1760 1746           * Fail ioctls which are logically "write" requests unless
1761 1747           * the user has write permission.
1762 1748           */
1763 1749          if ((flag & FWRITE) == 0 && isprwrioctl(cmd))
1764 1750                  return (EBADF);
1765 1751  
1766 1752          /*
     1753 +         * The following commands are no longer supported. They were present on
     1754 +         * SPARC and were always errors on other platforms. We now explicitly
     1755 +         * return ENOTSUP to indicate that this is no longer done.
     1756 +         */
     1757 +        switch (cmd) {
     1758 +        case PIOCSXREG:
     1759 +                return (ENOTSUP);
     1760 +        default:
     1761 +                break;
     1762 +        }
     1763 +
     1764 +        /*
1767 1765           * Perform any necessary copyin() operations before
1768 1766           * locking the process.  Helps avoid deadlocks and
1769 1767           * improves performance.
1770 1768           *
1771 1769           * Also, detect invalid ioctl codes here to avoid
1772      -         * locking a process unnnecessarily.
     1770 +         * locking a process unnecessarily.
1773 1771           *
1774 1772           * Also, prepare to allocate space that will be needed below,
1775 1773           * case by case.
1776 1774           */
1777 1775          error = 0;
1778 1776          switch (cmd) {
1779 1777          case PIOCGETPR:
1780 1778                  thingsize = sizeof (proc_t);
1781 1779                  break;
1782 1780          case PIOCGETU:
1783 1781                  thingsize = sizeof (user_t);
1784 1782                  break;
1785 1783          case PIOCSTOP:
1786 1784          case PIOCWSTOP:
1787 1785          case PIOCLWPIDS:
1788 1786          case PIOCGTRACE:
1789 1787          case PIOCGENTRY:
1790 1788          case PIOCGEXIT:
1791 1789          case PIOCSRLC:
1792 1790          case PIOCRRLC:
  
    | 
      ↓ open down ↓ | 
    10 lines elided | 
    
      ↑ open up ↑ | 
  
1793 1791          case PIOCSFORK:
1794 1792          case PIOCRFORK:
1795 1793          case PIOCGREG:
1796 1794          case PIOCGFPREG:
1797 1795          case PIOCSTATUS:
1798 1796          case PIOCLSTATUS:
1799 1797          case PIOCPSINFO:
1800 1798          case PIOCMAXSIG:
1801 1799          case PIOCGXREGSIZE:
1802 1800                  break;
1803      -        case PIOCSXREG:         /* set extra registers */
1804 1801          case PIOCGXREG:         /* get extra registers */
1805      -#if defined(__sparc)
1806      -                thingsize = sizeof (prxregset_t);
1807      -#else
1808      -                thingsize = 0;
1809      -#endif
     1802 +                thingsize = prgetprxregsize(p);
1810 1803                  break;
1811 1804          case PIOCACTION:
1812 1805                  thingsize = (nsig-1) * sizeof (struct sigaction32);
1813 1806                  break;
1814 1807          case PIOCGHOLD:
1815 1808          case PIOCNMAP:
1816 1809          case PIOCMAP:
1817 1810          case PIOCGFAULT:
1818 1811          case PIOCCFAULT:
1819 1812          case PIOCCRED:
1820 1813          case PIOCGROUPS:
1821 1814          case PIOCUSAGE:
1822 1815          case PIOCLUSAGE:
1823 1816                  break;
1824 1817          case PIOCOPENPD:
1825 1818                  /*
1826 1819                   * We will need this below.
1827 1820                   * Allocate it now, before locking the process.
1828 1821                   */
1829 1822                  xpnp = prgetnode(vp, PR_OPAGEDATA);
1830 1823                  break;
1831 1824          case PIOCNAUXV:
1832 1825          case PIOCAUXV:
1833 1826                  break;
1834 1827  
1835 1828  #if defined(__i386_COMPAT)
1836 1829          case PIOCNLDT:
1837 1830          case PIOCLDT:
1838 1831                  break;
1839 1832  #endif  /* __i386_COMPAT */
1840 1833  
1841 1834  #if defined(__sparc)
1842 1835          case PIOCGWIN:
1843 1836                  thingsize = sizeof (gwindows32_t);
1844 1837                  break;
1845 1838  #endif  /* __sparc */
1846 1839  
1847 1840          case PIOCOPENM:         /* open mapped object for reading */
1848 1841                  if (cmaddr == NULL)
1849 1842                          un32.va = (caddr32_t)(uintptr_t)NULL;
1850 1843                  else if (copyin(cmaddr, &un32.va, sizeof (un32.va)))
1851 1844                          error = EFAULT;
1852 1845                  break;
1853 1846  
1854 1847          case PIOCRUN:           /* make lwp or process runnable */
1855 1848                  if (cmaddr == NULL)
1856 1849                          un32.prrun.pr_flags = 0;
1857 1850                  else if (copyin(cmaddr, &un32.prrun, sizeof (un32.prrun)))
1858 1851                          error = EFAULT;
1859 1852                  break;
1860 1853  
1861 1854          case PIOCOPENLWP:       /* return /proc lwp file descriptor */
1862 1855                  if (copyin(cmaddr, &un32.lwpid, sizeof (un32.lwpid)))
1863 1856                          error = EFAULT;
1864 1857                  break;
1865 1858  
1866 1859          case PIOCSTRACE:        /* set signal trace mask */
1867 1860                  if (copyin(cmaddr, &un32.smask, sizeof (un32.smask)))
1868 1861                          error = EFAULT;
1869 1862                  break;
1870 1863  
1871 1864          case PIOCSSIG:          /* set current signal */
1872 1865                  if (cmaddr == NULL)
1873 1866                          un32.info.si_signo = 0;
1874 1867                  else if (copyin(cmaddr, &un32.info, sizeof (un32.info)))
1875 1868                          error = EFAULT;
1876 1869                  break;
1877 1870  
1878 1871          case PIOCKILL:          /* send signal */
1879 1872          case PIOCUNKILL:        /* delete a signal */
1880 1873                  if (copyin(cmaddr, &un32.signo, sizeof (un32.signo)))
1881 1874                          error = EFAULT;
1882 1875                  break;
1883 1876  
1884 1877          case PIOCNICE:          /* set nice priority */
1885 1878                  if (copyin(cmaddr, &un32.nice, sizeof (un32.nice)))
1886 1879                          error = EFAULT;
1887 1880                  break;
1888 1881  
1889 1882          case PIOCSENTRY:        /* set syscall entry bit mask */
1890 1883          case PIOCSEXIT:         /* set syscall exit bit mask */
1891 1884                  if (copyin(cmaddr, &un32.prmask, sizeof (un32.prmask)))
1892 1885                          error = EFAULT;
1893 1886                  break;
1894 1887  
1895 1888          case PIOCSET:           /* set process flags */
1896 1889          case PIOCRESET:         /* reset process flags */
1897 1890                  if (copyin(cmaddr, &un32.flags, sizeof (un32.flags)))
1898 1891                          error = EFAULT;
1899 1892                  break;
1900 1893  
1901 1894          case PIOCSREG:          /* set general registers */
1902 1895                  if (copyin(cmaddr, un32.regs, sizeof (un32.regs)))
1903 1896                          error = EFAULT;
1904 1897                  break;
1905 1898  
1906 1899          case PIOCSFPREG:        /* set floating-point registers */
1907 1900                  if (copyin(cmaddr, &un32.fpregs, sizeof (un32.fpregs)))
1908 1901                          error = EFAULT;
1909 1902                  break;
1910 1903  
1911 1904          case PIOCSHOLD:         /* set signal-hold mask */
1912 1905                  if (copyin(cmaddr, &un32.holdmask, sizeof (un32.holdmask)))
1913 1906                          error = EFAULT;
1914 1907                  break;
1915 1908  
1916 1909          case PIOCSFAULT:        /* set mask of traced faults */
1917 1910                  if (copyin(cmaddr, &un32.fltmask, sizeof (un32.fltmask)))
1918 1911                          error = EFAULT;
1919 1912                  break;
1920 1913  
1921 1914          default:
1922 1915                  error = EINVAL;
1923 1916                  break;
1924 1917          }
1925 1918  
1926 1919          if (error)
1927 1920                  return (error);
1928 1921  
1929 1922  startover:
1930 1923          /*
1931 1924           * If we need kmem_alloc()d space then we allocate it now, before
1932 1925           * grabbing the process lock.  Using kmem_alloc(KM_SLEEP) while
1933 1926           * holding the process lock leads to deadlock with the clock thread.
1934 1927           * (The clock thread wakes up the pageout daemon to free up space.
1935 1928           * If the clock thread blocks behind us and we are sleeping waiting
1936 1929           * for space, then space may never become available.)
1937 1930           */
1938 1931          if (thingsize) {
1939 1932                  ASSERT(thing == NULL);
  
    | 
      ↓ open down ↓ | 
    120 lines elided | 
    
      ↑ open up ↑ | 
  
1940 1933                  thing = kmem_alloc(thingsize, KM_SLEEP);
1941 1934          }
1942 1935  
1943 1936          switch (cmd) {
1944 1937          case PIOCPSINFO:
1945 1938          case PIOCGETPR:
1946 1939          case PIOCUSAGE:
1947 1940          case PIOCLUSAGE:
1948 1941                  zdisp = ZYES;
1949 1942                  break;
1950      -        case PIOCSXREG:         /* set extra registers */
1951      -                /*
1952      -                 * perform copyin before grabbing the process lock
1953      -                 */
1954      -                if (thing) {
1955      -                        if (copyin(cmaddr, thing, thingsize)) {
1956      -                                kmem_free(thing, thingsize);
1957      -                                return (EFAULT);
1958      -                        }
1959      -                }
1960      -                /* fall through... */
1961 1943          default:
1962 1944                  zdisp = ZNO;
1963 1945                  break;
1964 1946          }
1965 1947  
1966 1948          if ((error = prlock(pnp, zdisp)) != 0) {
1967 1949                  if (thing != NULL)
1968 1950                          kmem_free(thing, thingsize);
1969 1951                  if (xpnp)
1970 1952                          prfreenode(xpnp);
1971 1953                  return (error);
1972 1954          }
1973 1955  
1974 1956          pcp = pnp->pr_common;
1975 1957          p = pcp->prc_proc;
1976 1958          ASSERT(p != NULL);
1977 1959  
1978 1960          /*
1979 1961           * Choose a thread/lwp for the operation.
1980 1962           */
1981 1963          if (zdisp == ZNO && cmd != PIOCSTOP && cmd != PIOCWSTOP) {
1982 1964                  if (pnp->pr_type == PR_LWPIDFILE && cmd != PIOCLSTATUS) {
1983 1965                          t = pcp->prc_thread;
1984 1966                          ASSERT(t != NULL);
1985 1967                  } else {
1986 1968                          t = prchoose(p);        /* returns locked thread */
1987 1969                          ASSERT(t != NULL);
1988 1970                          thread_unlock(t);
1989 1971                  }
1990 1972                  lwp = ttolwp(t);
1991 1973          }
1992 1974  
1993 1975          error = 0;
1994 1976          switch (cmd) {
1995 1977  
1996 1978          case PIOCGETPR:         /* read struct proc */
1997 1979          {
1998 1980                  proc_t *prp = thing;
1999 1981  
2000 1982                  *prp = *p;
2001 1983                  prunlock(pnp);
2002 1984                  if (copyout(prp, cmaddr, sizeof (proc_t)))
2003 1985                          error = EFAULT;
2004 1986                  kmem_free(prp, sizeof (proc_t));
2005 1987                  thing = NULL;
2006 1988                  break;
2007 1989          }
2008 1990  
2009 1991          case PIOCGETU:          /* read u-area */
2010 1992          {
2011 1993                  user_t *userp = thing;
2012 1994  
2013 1995                  up = PTOU(p);
2014 1996                  *userp = *up;
2015 1997                  prunlock(pnp);
2016 1998                  if (copyout(userp, cmaddr, sizeof (user_t)))
2017 1999                          error = EFAULT;
2018 2000                  kmem_free(userp, sizeof (user_t));
2019 2001                  thing = NULL;
2020 2002                  break;
2021 2003          }
2022 2004  
2023 2005          case PIOCOPENM:         /* open mapped object for reading */
2024 2006                  if (PROCESS_NOT_32BIT(p) && cmaddr != NULL) {
2025 2007                          prunlock(pnp);
2026 2008                          error = EOVERFLOW;
2027 2009                          break;
2028 2010                  }
2029 2011                  error = propenm(pnp, cmaddr,
2030 2012                      (caddr_t)(uintptr_t)un32.va, rvalp, cr);
2031 2013                  /* propenm() called prunlock(pnp) */
2032 2014                  break;
2033 2015  
2034 2016          case PIOCSTOP:          /* stop process or lwp from running */
2035 2017          case PIOCWSTOP:         /* wait for process or lwp to stop */
2036 2018                  /*
2037 2019                   * Can't apply to a system process.
2038 2020                   */
2039 2021                  if ((p->p_flag & SSYS) || p->p_as == &kas) {
2040 2022                          prunlock(pnp);
2041 2023                          error = EBUSY;
2042 2024                          break;
2043 2025                  }
2044 2026  
2045 2027                  if (cmd == PIOCSTOP)
2046 2028                          pr_stop(pnp);
2047 2029  
2048 2030                  /*
2049 2031                   * If an lwp is waiting for itself or its process, don't wait.
2050 2032                   * The lwp will never see the fact that itself is stopped.
2051 2033                   */
2052 2034                  if ((pnp->pr_type == PR_LWPIDFILE)?
2053 2035                      (pcp->prc_thread == curthread) : (p == curproc)) {
2054 2036                          if (cmd == PIOCWSTOP)
2055 2037                                  error = EBUSY;
2056 2038                          prunlock(pnp);
2057 2039                          break;
2058 2040                  }
2059 2041  
2060 2042                  if ((error = pr_wait_stop(pnp, (time_t)0)) != 0)
2061 2043                          break;  /* pr_wait_stop() unlocked the process */
2062 2044  
2063 2045                  if (cmaddr == NULL)
2064 2046                          prunlock(pnp);
2065 2047                  else if (PROCESS_NOT_32BIT(p)) {
2066 2048                          prunlock(pnp);
2067 2049                          error = EOVERFLOW;
2068 2050                  } else {
2069 2051                          /*
2070 2052                           * Return process/lwp status information.
2071 2053                           */
2072 2054                          t = pr_thread(pnp);     /* returns locked thread */
2073 2055                          thread_unlock(t);
2074 2056                          oprgetstatus32(t, &un32.prstat, VTOZONE(vp));
2075 2057                          prunlock(pnp);
2076 2058                          if (copyout(&un32.prstat, cmaddr, sizeof (un32.prstat)))
2077 2059                                  error = EFAULT;
2078 2060                  }
2079 2061                  break;
2080 2062  
2081 2063          case PIOCRUN:           /* make lwp or process runnable */
2082 2064          {
2083 2065                  long flags = un32.prrun.pr_flags;
2084 2066  
2085 2067                  /*
2086 2068                   * Cannot set an lwp running is it is not stopped.
2087 2069                   * Also, no lwp other than the /proc agent lwp can
2088 2070                   * be set running so long as the /proc agent lwp exists.
2089 2071                   */
2090 2072                  if ((!ISTOPPED(t) && !VSTOPPED(t) &&
2091 2073                      !(t->t_proc_flag & TP_PRSTOP)) ||
2092 2074                      (p->p_agenttp != NULL &&
2093 2075                      (t != p->p_agenttp || pnp->pr_type != PR_LWPIDFILE))) {
2094 2076                          prunlock(pnp);
2095 2077                          error = EBUSY;
2096 2078                          break;
2097 2079                  }
2098 2080  
2099 2081                  if ((flags & PRSVADDR) && PROCESS_NOT_32BIT(p)) {
2100 2082                          prunlock(pnp);
2101 2083                          error = EOVERFLOW;
2102 2084                          break;
2103 2085                  }
2104 2086  
2105 2087                  if (flags & (PRSHOLD|PRSTRACE|PRSFAULT|PRSVADDR)) {
2106 2088                          un.prrun.pr_flags = (int)flags;
2107 2089                          un.prrun.pr_trace = un32.prrun.pr_trace;
2108 2090                          un.prrun.pr_sighold = un32.prrun.pr_sighold;
2109 2091                          un.prrun.pr_fault = un32.prrun.pr_fault;
2110 2092                          un.prrun.pr_vaddr =
2111 2093                              (caddr_t)(uintptr_t)un32.prrun.pr_vaddr;
2112 2094                          prsetrun(t, &un.prrun);
2113 2095                  }
2114 2096  
2115 2097                  error = pr_setrun(pnp, prmaprunflags(flags));
2116 2098  
2117 2099                  prunlock(pnp);
2118 2100                  break;
2119 2101          }
2120 2102  
2121 2103          case PIOCLWPIDS:        /* get array of lwp identifiers */
2122 2104          {
2123 2105                  int nlwp;
2124 2106                  int Nlwp;
2125 2107                  id_t *idp;
2126 2108                  id_t *Bidp;
2127 2109  
2128 2110                  Nlwp = nlwp = p->p_lwpcnt;
2129 2111  
2130 2112                  if (thing && thingsize != (Nlwp+1) * sizeof (id_t)) {
2131 2113                          kmem_free(thing, thingsize);
2132 2114                          thing = NULL;
2133 2115                  }
2134 2116                  if (thing == NULL) {
2135 2117                          thingsize = (Nlwp+1) * sizeof (id_t);
2136 2118                          thing = kmem_alloc(thingsize, KM_NOSLEEP);
2137 2119                  }
2138 2120                  if (thing == NULL) {
2139 2121                          prunlock(pnp);
2140 2122                          goto startover;
2141 2123                  }
2142 2124  
2143 2125                  idp = thing;
2144 2126                  thing = NULL;
2145 2127                  Bidp = idp;
2146 2128                  if ((t = p->p_tlist) != NULL) {
2147 2129                          do {
2148 2130                                  ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
2149 2131                                  ASSERT(nlwp > 0);
2150 2132                                  --nlwp;
2151 2133                                  *idp++ = t->t_tid;
2152 2134                          } while ((t = t->t_forw) != p->p_tlist);
2153 2135                  }
2154 2136                  *idp = 0;
2155 2137                  ASSERT(nlwp == 0);
2156 2138                  prunlock(pnp);
2157 2139                  if (copyout(Bidp, cmaddr, (Nlwp+1) * sizeof (id_t)))
2158 2140                          error = EFAULT;
2159 2141                  kmem_free(Bidp, (Nlwp+1) * sizeof (id_t));
2160 2142                  break;
2161 2143          }
2162 2144  
2163 2145          case PIOCOPENLWP:       /* return /proc lwp file descriptor */
2164 2146          {
2165 2147                  vnode_t *xvp;
2166 2148                  int n;
2167 2149  
2168 2150                  prunlock(pnp);
2169 2151                  if ((xvp = prlwpnode(pnp, un32.lwpid)) == NULL)
2170 2152                          error = ENOENT;
2171 2153                  else if (error = fassign(&xvp, flag & (FREAD|FWRITE), &n)) {
2172 2154                          VN_RELE(xvp);
2173 2155                  } else
2174 2156                          *rvalp = n;
2175 2157                  break;
2176 2158          }
2177 2159  
2178 2160          case PIOCOPENPD:        /* return /proc page data file descriptor */
2179 2161          {
2180 2162                  vnode_t *xvp = PTOV(xpnp);
2181 2163                  vnode_t *dp = pnp->pr_parent;
2182 2164                  int n;
2183 2165  
2184 2166                  if (PROCESS_NOT_32BIT(p)) {
2185 2167                          prunlock(pnp);
2186 2168                          prfreenode(xpnp);
2187 2169                          xpnp = NULL;
2188 2170                          error = EOVERFLOW;
2189 2171                          break;
2190 2172                  }
2191 2173  
2192 2174                  if (pnp->pr_type == PR_LWPIDFILE) {
2193 2175                          dp = VTOP(dp)->pr_parent;
2194 2176                          dp = VTOP(dp)->pr_parent;
2195 2177                  }
2196 2178                  ASSERT(VTOP(dp)->pr_type == PR_PIDDIR);
2197 2179  
2198 2180                  VN_HOLD(dp);
2199 2181                  pcp = pnp->pr_pcommon;
2200 2182                  xpnp->pr_ino = ptoi(pcp->prc_pid);
2201 2183                  xpnp->pr_common = pcp;
2202 2184                  xpnp->pr_pcommon = pcp;
2203 2185                  xpnp->pr_parent = dp;
2204 2186  
2205 2187                  xpnp->pr_next = p->p_plist;
2206 2188                  p->p_plist = xvp;
2207 2189  
2208 2190                  prunlock(pnp);
2209 2191                  if (error = fassign(&xvp, FREAD, &n)) {
2210 2192                          VN_RELE(xvp);
2211 2193                  } else
2212 2194                          *rvalp = n;
2213 2195  
2214 2196                  xpnp = NULL;
2215 2197                  break;
2216 2198          }
2217 2199  
2218 2200          case PIOCGTRACE:        /* get signal trace mask */
2219 2201                  prassignset(&un32.smask, &p->p_sigmask);
2220 2202                  prunlock(pnp);
2221 2203                  if (copyout(&un32.smask, cmaddr, sizeof (un32.smask)))
2222 2204                          error = EFAULT;
2223 2205                  break;
2224 2206  
2225 2207          case PIOCSTRACE:        /* set signal trace mask */
2226 2208                  prdelset(&un32.smask, SIGKILL);
2227 2209                  prassignset(&p->p_sigmask, &un32.smask);
2228 2210                  if (!sigisempty(&p->p_sigmask))
2229 2211                          p->p_proc_flag |= P_PR_TRACE;
2230 2212                  else if (prisempty(&p->p_fltmask)) {
2231 2213                          up = PTOU(p);
2232 2214                          if (up->u_systrap == 0)
2233 2215                                  p->p_proc_flag &= ~P_PR_TRACE;
2234 2216                  }
2235 2217                  prunlock(pnp);
2236 2218                  break;
2237 2219  
2238 2220          case PIOCSSIG:          /* set current signal */
2239 2221                  if (un32.info.si_signo != 0 && PROCESS_NOT_32BIT(p)) {
2240 2222                          prunlock(pnp);
2241 2223                          error = EOVERFLOW;
2242 2224                  } else {
2243 2225                          bzero(&un.info, sizeof (un.info));
2244 2226                          siginfo_32tok(&un32.info, (k_siginfo_t *)&un.info);
2245 2227                          error = pr_setsig(pnp, &un.info);
2246 2228                          prunlock(pnp);
2247 2229                          if (un32.info.si_signo == SIGKILL && error == 0)
2248 2230                                  pr_wait_die(pnp);
2249 2231                  }
2250 2232                  break;
2251 2233  
2252 2234          case PIOCKILL:          /* send signal */
2253 2235                  error = pr_kill(pnp, un32.signo, cr);
2254 2236                  prunlock(pnp);
2255 2237                  if (un32.signo == SIGKILL && error == 0)
2256 2238                          pr_wait_die(pnp);
2257 2239                  break;
2258 2240  
2259 2241          case PIOCUNKILL:        /* delete a signal */
2260 2242                  error = pr_unkill(pnp, un32.signo);
2261 2243                  prunlock(pnp);
2262 2244                  break;
2263 2245  
2264 2246          case PIOCNICE:          /* set nice priority */
2265 2247                  error = pr_nice(p, un32.nice, cr);
2266 2248                  prunlock(pnp);
2267 2249                  break;
2268 2250  
2269 2251          case PIOCGENTRY:        /* get syscall entry bit mask */
2270 2252          case PIOCGEXIT:         /* get syscall exit bit mask */
2271 2253                  up = PTOU(p);
2272 2254                  if (cmd == PIOCGENTRY) {
2273 2255                          prassignset(&un32.prmask, &up->u_entrymask);
2274 2256                  } else {
2275 2257                          prassignset(&un32.prmask, &up->u_exitmask);
2276 2258                  }
2277 2259                  prunlock(pnp);
2278 2260                  if (copyout(&un32.prmask, cmaddr, sizeof (un32.prmask)))
2279 2261                          error = EFAULT;
2280 2262                  break;
2281 2263  
2282 2264          case PIOCSENTRY:        /* set syscall entry bit mask */
2283 2265          case PIOCSEXIT:         /* set syscall exit bit mask */
2284 2266                  pr_setentryexit(p, &un32.prmask, cmd == PIOCSENTRY);
2285 2267                  prunlock(pnp);
2286 2268                  break;
2287 2269  
2288 2270          case PIOCSRLC:          /* obsolete: set running on last /proc close */
2289 2271                  error = pr_set(p, prmapsetflags(PR_RLC));
2290 2272                  prunlock(pnp);
2291 2273                  break;
2292 2274  
2293 2275          case PIOCRRLC:          /* obsolete: reset run-on-last-close flag */
2294 2276                  error = pr_unset(p, prmapsetflags(PR_RLC));
2295 2277                  prunlock(pnp);
2296 2278                  break;
2297 2279  
2298 2280          case PIOCSFORK:         /* obsolete: set inherit-on-fork flag */
2299 2281                  error = pr_set(p, prmapsetflags(PR_FORK));
2300 2282                  prunlock(pnp);
2301 2283                  break;
2302 2284  
2303 2285          case PIOCRFORK:         /* obsolete: reset inherit-on-fork flag */
2304 2286                  error = pr_unset(p, prmapsetflags(PR_FORK));
2305 2287                  prunlock(pnp);
2306 2288                  break;
2307 2289  
2308 2290          case PIOCSET:           /* set process flags */
2309 2291                  error = pr_set(p, prmapsetflags((long)un32.flags));
2310 2292                  prunlock(pnp);
2311 2293                  break;
2312 2294  
2313 2295          case PIOCRESET:         /* reset process flags */
2314 2296                  error = pr_unset(p, prmapsetflags((long)un32.flags));
2315 2297                  prunlock(pnp);
2316 2298                  break;
2317 2299  
2318 2300          case PIOCGREG:          /* get general registers */
2319 2301                  if (PROCESS_NOT_32BIT(p))
2320 2302                          error = EOVERFLOW;
2321 2303                  else if (t->t_state != TS_STOPPED && !VSTOPPED(t))
2322 2304                          bzero(un32.regs, sizeof (un32.regs));
2323 2305                  else {
2324 2306                          /* drop p_lock while touching the lwp's stack */
2325 2307                          mutex_exit(&p->p_lock);
2326 2308                          prgetprregs32(lwp, un32.regs);
2327 2309                          mutex_enter(&p->p_lock);
2328 2310                  }
2329 2311                  prunlock(pnp);
2330 2312                  if (error == 0 &&
2331 2313                      copyout(un32.regs, cmaddr, sizeof (un32.regs)))
2332 2314                          error = EFAULT;
2333 2315                  break;
2334 2316  
2335 2317          case PIOCSREG:          /* set general registers */
2336 2318                  if (PROCESS_NOT_32BIT(p))
2337 2319                          error = EOVERFLOW;
2338 2320                  else if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
2339 2321                          error = EBUSY;
2340 2322                  else {
2341 2323                          /* drop p_lock while touching the lwp's stack */
2342 2324                          mutex_exit(&p->p_lock);
2343 2325                          prgregset_32ton(lwp, un32.regs, un.regs);
2344 2326                          prsetprregs(lwp, un.regs, 0);
2345 2327                          mutex_enter(&p->p_lock);
2346 2328                  }
2347 2329                  prunlock(pnp);
2348 2330                  break;
2349 2331  
2350 2332          case PIOCGFPREG:        /* get floating-point registers */
2351 2333                  if (!prhasfp())
2352 2334                          error = EINVAL; /* No FP support */
2353 2335                  else if (PROCESS_NOT_32BIT(p))
2354 2336                          error = EOVERFLOW;
2355 2337                  else if (t->t_state != TS_STOPPED && !VSTOPPED(t))
2356 2338                          bzero(&un32.fpregs, sizeof (un32.fpregs));
2357 2339                  else {
2358 2340                          /* drop p_lock while touching the lwp's stack */
2359 2341                          mutex_exit(&p->p_lock);
2360 2342                          prgetprfpregs32(lwp, &un32.fpregs);
2361 2343                          mutex_enter(&p->p_lock);
2362 2344                  }
2363 2345                  prunlock(pnp);
2364 2346                  if (error == 0 &&
2365 2347                      copyout(&un32.fpregs, cmaddr, sizeof (un32.fpregs)))
2366 2348                          error = EFAULT;
2367 2349                  break;
2368 2350  
2369 2351          case PIOCSFPREG:        /* set floating-point registers */
2370 2352                  if (!prhasfp())
2371 2353                          error = EINVAL; /* No FP support */
2372 2354                  else if (PROCESS_NOT_32BIT(p))
2373 2355                          error = EOVERFLOW;
2374 2356                  else if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
2375 2357                          error = EBUSY;
2376 2358                  else {
  
    | 
      ↓ open down ↓ | 
    406 lines elided | 
    
      ↑ open up ↑ | 
  
2377 2359                          /* drop p_lock while touching the lwp's stack */
2378 2360                          mutex_exit(&p->p_lock);
2379 2361                          prsetprfpregs32(lwp, &un32.fpregs);
2380 2362                          mutex_enter(&p->p_lock);
2381 2363                  }
2382 2364                  prunlock(pnp);
2383 2365                  break;
2384 2366  
2385 2367          case PIOCGXREGSIZE:     /* get the size of the extra registers */
2386 2368          {
2387      -                int xregsize;
2388      -
2389 2369                  if (prhasx(p)) {
     2370 +                        size_t xregsize;
     2371 +                        int abisize;
     2372 +
2390 2373                          xregsize = prgetprxregsize(p);
2391 2374                          prunlock(pnp);
2392      -                        if (copyout(&xregsize, cmaddr, sizeof (xregsize)))
     2375 +                        if (xregsize > INT_MAX) {
     2376 +                                error = EOVERFLOW;
     2377 +                                break;
     2378 +                        }
     2379 +
     2380 +                        abisize = (int)xregsize;
     2381 +                        if (copyout(&abisize, cmaddr, sizeof (abisize)))
2393 2382                                  error = EFAULT;
2394 2383                  } else {
2395 2384                          prunlock(pnp);
2396 2385                          error = EINVAL; /* No extra register support */
2397 2386                  }
2398 2387                  break;
2399 2388          }
2400 2389  
2401 2390          case PIOCGXREG:         /* get extra registers */
2402 2391                  if (PROCESS_NOT_32BIT(p))
2403 2392                          error = EOVERFLOW;
2404 2393                  else if (!prhasx(p))
2405 2394                          error = EINVAL; /* No extra register support */
2406 2395                  else {
2407 2396                          bzero(thing, thingsize);
2408 2397                          if (t->t_state == TS_STOPPED || VSTOPPED(t)) {
2409 2398                                  /* drop p_lock to touch the stack */
2410 2399                                  mutex_exit(&p->p_lock);
  
    | 
      ↓ open down ↓ | 
    8 lines elided | 
    
      ↑ open up ↑ | 
  
2411 2400                                  prgetprxregs(lwp, thing);
2412 2401                                  mutex_enter(&p->p_lock);
2413 2402                          }
2414 2403                  }
2415 2404                  prunlock(pnp);
2416 2405                  if (error == 0 &&
2417 2406                      copyout(thing, cmaddr, thingsize))
2418 2407                          error = EFAULT;
2419 2408                  if (thing) {
2420 2409                          kmem_free(thing, thingsize);
2421      -                        thing = NULL;
2422      -                }
2423      -                break;
2424      -
2425      -        case PIOCSXREG:         /* set extra registers */
2426      -                if (PROCESS_NOT_32BIT(p))
2427      -                        error = EOVERFLOW;
2428      -                else if (!ISTOPPED(t) && !VSTOPPED(t) && !DSTOPPED(t))
2429      -                        error = EBUSY;
2430      -                else if (!prhasx(p))
2431      -                        error = EINVAL; /* No extra register support */
2432      -                else if (thing) {
2433      -                        /* drop p_lock while touching the lwp's stack */
2434      -                        mutex_exit(&p->p_lock);
2435      -                        prsetprxregs(lwp, thing);
2436      -                        mutex_enter(&p->p_lock);
2437      -                }
2438      -                prunlock(pnp);
2439      -                if (thing) {
2440      -                        kmem_free(thing, thingsize);
2441 2410                          thing = NULL;
2442 2411                  }
2443 2412                  break;
2444 2413  
2445 2414          case PIOCSTATUS:        /* get process/lwp status */
2446 2415                  if (PROCESS_NOT_32BIT(p)) {
2447 2416                          prunlock(pnp);
2448 2417                          error = EOVERFLOW;
2449 2418                          break;
2450 2419                  }
2451 2420                  oprgetstatus32(t, &un32.prstat, VTOZONE(vp));
2452 2421                  prunlock(pnp);
2453 2422                  if (copyout(&un32.prstat, cmaddr, sizeof (un32.prstat)))
2454 2423                          error = EFAULT;
2455 2424                  break;
2456 2425  
2457 2426          case PIOCLSTATUS:       /* get status for process & all lwps */
2458 2427          {
2459 2428                  int Nlwp;
2460 2429                  int nlwp;
2461 2430                  prstatus32_t *Bprsp;
2462 2431                  prstatus32_t *prsp;
2463 2432  
2464 2433                  if (PROCESS_NOT_32BIT(p)) {
2465 2434                          prunlock(pnp);
2466 2435                          if (thing) {
2467 2436                                  kmem_free(thing, thingsize);
2468 2437                                  thing = NULL;
2469 2438                          }
2470 2439                          error = EOVERFLOW;
2471 2440                          break;
2472 2441                  }
2473 2442  
2474 2443                  nlwp = Nlwp = p->p_lwpcnt;
2475 2444  
2476 2445                  if (thing && thingsize != (Nlwp+1) * sizeof (prstatus32_t)) {
2477 2446                          kmem_free(thing, thingsize);
2478 2447                          thing = NULL;
2479 2448                  }
2480 2449                  if (thing == NULL) {
2481 2450                          thingsize = (Nlwp+1) * sizeof (prstatus32_t);
2482 2451                          thing = kmem_alloc(thingsize, KM_NOSLEEP);
2483 2452                  }
2484 2453                  if (thing == NULL) {
2485 2454                          prunlock(pnp);
2486 2455                          goto startover;
2487 2456                  }
2488 2457  
2489 2458                  Bprsp = (prstatus32_t *)thing;
2490 2459                  thing = NULL;
2491 2460                  prsp = Bprsp;
2492 2461                  oprgetstatus32(t, prsp, VTOZONE(vp));
2493 2462                  t = p->p_tlist;
2494 2463                  do {
2495 2464                          ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
2496 2465                          ASSERT(nlwp > 0);
2497 2466                          --nlwp;
2498 2467                          oprgetstatus32(t, ++prsp, VTOZONE(vp));
2499 2468                  } while ((t = t->t_forw) != p->p_tlist);
2500 2469                  ASSERT(nlwp == 0);
2501 2470                  prunlock(pnp);
2502 2471                  if (copyout(Bprsp, cmaddr, (Nlwp+1) * sizeof (prstatus32_t)))
2503 2472                          error = EFAULT;
2504 2473  
2505 2474                  kmem_free(Bprsp, (Nlwp + 1) * sizeof (prstatus32_t));
2506 2475                  break;
2507 2476          }
2508 2477  
2509 2478          case PIOCPSINFO:        /* get ps(1) information */
2510 2479          {
2511 2480                  prpsinfo32_t *psp = &un32.prps;
2512 2481  
2513 2482                  oprgetpsinfo32(p, psp,
2514 2483                      (pnp->pr_type == PR_LWPIDFILE)? pcp->prc_thread : NULL);
2515 2484  
2516 2485                  prunlock(pnp);
2517 2486                  if (copyout(&un32.prps, cmaddr, sizeof (un32.prps)))
2518 2487                          error = EFAULT;
2519 2488                  break;
2520 2489          }
2521 2490  
2522 2491          case PIOCMAXSIG:        /* get maximum signal number */
2523 2492          {
2524 2493                  int n = nsig-1;
2525 2494  
2526 2495                  prunlock(pnp);
2527 2496                  if (copyout(&n, cmaddr, sizeof (int)))
2528 2497                          error = EFAULT;
2529 2498                  break;
2530 2499          }
2531 2500  
2532 2501          case PIOCACTION:        /* get signal action structures */
2533 2502          {
2534 2503                  uint_t sig;
2535 2504                  struct sigaction32 *sap = thing;
2536 2505  
2537 2506                  if (PROCESS_NOT_32BIT(p))
2538 2507                          error = EOVERFLOW;
2539 2508                  else {
2540 2509                          up = PTOU(p);
2541 2510                          for (sig = 1; sig < nsig; sig++)
2542 2511                                  prgetaction32(p, up, sig, &sap[sig-1]);
2543 2512                  }
2544 2513                  prunlock(pnp);
2545 2514                  if (error == 0 &&
2546 2515                      copyout(sap, cmaddr, (nsig-1)*sizeof (struct sigaction32)))
2547 2516                          error = EFAULT;
2548 2517                  kmem_free(sap, (nsig-1)*sizeof (struct sigaction32));
2549 2518                  thing = NULL;
2550 2519                  break;
2551 2520          }
2552 2521  
2553 2522          case PIOCGHOLD:         /* get signal-hold mask */
2554 2523                  prgethold(t, &un32.holdmask);
2555 2524                  prunlock(pnp);
2556 2525                  if (copyout(&un32.holdmask, cmaddr, sizeof (un32.holdmask)))
2557 2526                          error = EFAULT;
2558 2527                  break;
2559 2528  
2560 2529          case PIOCSHOLD:         /* set signal-hold mask */
2561 2530                  pr_sethold(pnp, &un32.holdmask);
2562 2531                  prunlock(pnp);
2563 2532                  break;
2564 2533  
2565 2534          case PIOCNMAP:          /* get number of memory mappings */
2566 2535          {
2567 2536                  uint_t n;
2568 2537                  struct as *as = p->p_as;
2569 2538  
2570 2539                  if ((p->p_flag & SSYS) || as == &kas)
2571 2540                          n = 0;
2572 2541                  else {
2573 2542                          mutex_exit(&p->p_lock);
2574 2543                          AS_LOCK_ENTER(as, RW_WRITER);
2575 2544                          n = prnsegs(as, 0);
2576 2545                          AS_LOCK_EXIT(as);
2577 2546                          mutex_enter(&p->p_lock);
2578 2547                  }
2579 2548                  prunlock(pnp);
2580 2549                  if (copyout(&n, cmaddr, sizeof (uint_t)))
2581 2550                          error = EFAULT;
2582 2551                  break;
2583 2552          }
2584 2553  
2585 2554          case PIOCMAP:           /* get memory map information */
2586 2555          {
2587 2556                  list_t iolhead;
2588 2557                  struct as *as = p->p_as;
2589 2558  
2590 2559                  if ((p->p_flag & SSYS) || as == &kas) {
2591 2560                          error = 0;
2592 2561                          prunlock(pnp);
2593 2562                  } else if (PROCESS_NOT_32BIT(p)) {
2594 2563                          error = EOVERFLOW;
2595 2564                          prunlock(pnp);
2596 2565                  } else {
2597 2566                          mutex_exit(&p->p_lock);
2598 2567                          AS_LOCK_ENTER(as, RW_WRITER);
2599 2568                          error = oprgetmap32(p, &iolhead);
2600 2569                          AS_LOCK_EXIT(as);
2601 2570                          mutex_enter(&p->p_lock);
2602 2571                          prunlock(pnp);
2603 2572  
2604 2573                          error = pr_iol_copyout_and_free(&iolhead,
2605 2574                              &cmaddr, error);
2606 2575                  }
2607 2576                  /*
2608 2577                   * The procfs PIOCMAP ioctl returns an all-zero buffer
2609 2578                   * to indicate the end of the prmap[] array.
2610 2579                   * Append it to whatever has already been copied out.
2611 2580                   */
2612 2581                  bzero(&un32.prmap, sizeof (un32.prmap));
2613 2582                  if (!error &&
2614 2583                      copyout(&un32.prmap, cmaddr, sizeof (un32.prmap)))
2615 2584                                  error = EFAULT;
2616 2585                  break;
2617 2586          }
2618 2587  
2619 2588          case PIOCGFAULT:        /* get mask of traced faults */
2620 2589                  prassignset(&un32.fltmask, &p->p_fltmask);
2621 2590                  prunlock(pnp);
2622 2591                  if (copyout(&un32.fltmask, cmaddr, sizeof (un32.fltmask)))
2623 2592                          error = EFAULT;
2624 2593                  break;
2625 2594  
2626 2595          case PIOCSFAULT:        /* set mask of traced faults */
2627 2596                  pr_setfault(p, &un32.fltmask);
2628 2597                  prunlock(pnp);
2629 2598                  break;
2630 2599  
2631 2600          case PIOCCFAULT:        /* clear current fault */
2632 2601                  lwp->lwp_curflt = 0;
2633 2602                  prunlock(pnp);
2634 2603                  break;
2635 2604  
2636 2605          case PIOCCRED:          /* get process credentials */
2637 2606          {
2638 2607                  cred_t *cp;
2639 2608  
2640 2609                  mutex_enter(&p->p_crlock);
2641 2610                  cp = p->p_cred;
2642 2611                  un32.prcred.pr_euid = crgetuid(cp);
2643 2612                  un32.prcred.pr_ruid = crgetruid(cp);
2644 2613                  un32.prcred.pr_suid = crgetsuid(cp);
2645 2614                  un32.prcred.pr_egid = crgetgid(cp);
2646 2615                  un32.prcred.pr_rgid = crgetrgid(cp);
2647 2616                  un32.prcred.pr_sgid = crgetsgid(cp);
2648 2617                  un32.prcred.pr_ngroups = crgetngroups(cp);
2649 2618                  mutex_exit(&p->p_crlock);
2650 2619  
2651 2620                  prunlock(pnp);
2652 2621                  if (copyout(&un32.prcred, cmaddr, sizeof (un32.prcred)))
2653 2622                          error = EFAULT;
2654 2623                  break;
2655 2624          }
2656 2625  
2657 2626          case PIOCGROUPS:        /* get supplementary groups */
2658 2627          {
2659 2628                  cred_t *cp;
2660 2629  
2661 2630                  mutex_enter(&p->p_crlock);
2662 2631                  cp = p->p_cred;
2663 2632                  crhold(cp);
2664 2633                  mutex_exit(&p->p_crlock);
2665 2634  
2666 2635                  prunlock(pnp);
2667 2636                  if (copyout(crgetgroups(cp), cmaddr,
2668 2637                      MAX(crgetngroups(cp), 1) * sizeof (gid_t)))
2669 2638                          error = EFAULT;
2670 2639                  crfree(cp);
2671 2640                  break;
2672 2641          }
2673 2642  
2674 2643          case PIOCUSAGE:         /* get usage info */
2675 2644          {
2676 2645                  /*
2677 2646                   * For an lwp file descriptor, return just the lwp usage.
2678 2647                   * For a process file descriptor, return total usage,
2679 2648                   * all current lwps plus all defunct lwps.
2680 2649                   */
2681 2650                  prhusage_t *pup = &un32.prhusage;
2682 2651                  prusage32_t *upup;
2683 2652  
2684 2653                  bzero(pup, sizeof (*pup));
2685 2654                  pup->pr_tstamp = gethrtime();
2686 2655  
2687 2656                  if (pnp->pr_type == PR_LWPIDFILE) {
2688 2657                          t = pcp->prc_thread;
2689 2658                          if (t != NULL)
2690 2659                                  prgetusage(t, pup);
2691 2660                          else
2692 2661                                  error = ENOENT;
2693 2662                  } else {
2694 2663                          pup->pr_count  = p->p_defunct;
2695 2664                          pup->pr_create = p->p_mstart;
2696 2665                          pup->pr_term   = p->p_mterm;
2697 2666  
2698 2667                          pup->pr_rtime    = p->p_mlreal;
2699 2668                          pup->pr_utime    = p->p_acct[LMS_USER];
2700 2669                          pup->pr_stime    = p->p_acct[LMS_SYSTEM];
2701 2670                          pup->pr_ttime    = p->p_acct[LMS_TRAP];
2702 2671                          pup->pr_tftime   = p->p_acct[LMS_TFAULT];
2703 2672                          pup->pr_dftime   = p->p_acct[LMS_DFAULT];
2704 2673                          pup->pr_kftime   = p->p_acct[LMS_KFAULT];
2705 2674                          pup->pr_ltime    = p->p_acct[LMS_USER_LOCK];
2706 2675                          pup->pr_slptime  = p->p_acct[LMS_SLEEP];
2707 2676                          pup->pr_wtime    = p->p_acct[LMS_WAIT_CPU];
2708 2677                          pup->pr_stoptime = p->p_acct[LMS_STOPPED];
2709 2678  
2710 2679                          pup->pr_minf  = p->p_ru.minflt;
2711 2680                          pup->pr_majf  = p->p_ru.majflt;
2712 2681                          pup->pr_nswap = p->p_ru.nswap;
2713 2682                          pup->pr_inblk = p->p_ru.inblock;
2714 2683                          pup->pr_oublk = p->p_ru.oublock;
2715 2684                          pup->pr_msnd  = p->p_ru.msgsnd;
2716 2685                          pup->pr_mrcv  = p->p_ru.msgrcv;
2717 2686                          pup->pr_sigs  = p->p_ru.nsignals;
2718 2687                          pup->pr_vctx  = p->p_ru.nvcsw;
2719 2688                          pup->pr_ictx  = p->p_ru.nivcsw;
2720 2689                          pup->pr_sysc  = p->p_ru.sysc;
2721 2690                          pup->pr_ioch  = p->p_ru.ioch;
2722 2691  
2723 2692                          /*
2724 2693                           * Add the usage information for each active lwp.
2725 2694                           */
2726 2695                          if ((t = p->p_tlist) != NULL &&
2727 2696                              !(pcp->prc_flags & PRC_DESTROY)) {
2728 2697                                  do {
2729 2698                                          ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
2730 2699                                          pup->pr_count++;
2731 2700                                          praddusage(t, pup);
2732 2701                                  } while ((t = t->t_forw) != p->p_tlist);
2733 2702                          }
2734 2703                  }
2735 2704  
2736 2705                  prunlock(pnp);
2737 2706  
2738 2707                  upup = kmem_alloc(sizeof (*upup), KM_SLEEP);
2739 2708                  prcvtusage32(pup, upup);
2740 2709                  if (copyout(upup, cmaddr, sizeof (*upup)))
2741 2710                          error = EFAULT;
2742 2711                  kmem_free(upup, sizeof (*upup));
2743 2712  
2744 2713                  break;
2745 2714          }
2746 2715  
2747 2716          case PIOCLUSAGE:        /* get detailed usage info */
2748 2717          {
2749 2718                  int Nlwp;
2750 2719                  int nlwp;
2751 2720                  prusage32_t *upup;
2752 2721                  prusage32_t *Bupup;
2753 2722                  prhusage_t *pup;
2754 2723                  hrtime_t curtime;
2755 2724  
2756 2725                  nlwp = Nlwp = (pcp->prc_flags & PRC_DESTROY)? 0 : p->p_lwpcnt;
2757 2726  
2758 2727                  if (thing && thingsize !=
2759 2728                      sizeof (prhusage_t) + (Nlwp+1) * sizeof (prusage32_t)) {
2760 2729                          kmem_free(thing, thingsize);
2761 2730                          thing = NULL;
2762 2731                  }
2763 2732                  if (thing == NULL) {
2764 2733                          thingsize = sizeof (prhusage_t) +
2765 2734                              (Nlwp+1) * sizeof (prusage32_t);
2766 2735                          thing = kmem_alloc(thingsize, KM_NOSLEEP);
2767 2736                  }
2768 2737                  if (thing == NULL) {
2769 2738                          prunlock(pnp);
2770 2739                          goto startover;
2771 2740                  }
2772 2741  
2773 2742                  pup = (prhusage_t *)thing;
2774 2743                  upup = Bupup = (prusage32_t *)(pup + 1);
2775 2744  
2776 2745                  ASSERT(p == pcp->prc_proc);
2777 2746  
2778 2747                  curtime = gethrtime();
2779 2748  
2780 2749                  /*
2781 2750                   * First the summation over defunct lwps.
2782 2751                   */
2783 2752                  bzero(pup, sizeof (*pup));
2784 2753                  pup->pr_count  = p->p_defunct;
2785 2754                  pup->pr_tstamp = curtime;
2786 2755                  pup->pr_create = p->p_mstart;
2787 2756                  pup->pr_term   = p->p_mterm;
2788 2757  
2789 2758                  pup->pr_rtime    = p->p_mlreal;
2790 2759                  pup->pr_utime    = p->p_acct[LMS_USER];
2791 2760                  pup->pr_stime    = p->p_acct[LMS_SYSTEM];
2792 2761                  pup->pr_ttime    = p->p_acct[LMS_TRAP];
2793 2762                  pup->pr_tftime   = p->p_acct[LMS_TFAULT];
2794 2763                  pup->pr_dftime   = p->p_acct[LMS_DFAULT];
2795 2764                  pup->pr_kftime   = p->p_acct[LMS_KFAULT];
2796 2765                  pup->pr_ltime    = p->p_acct[LMS_USER_LOCK];
2797 2766                  pup->pr_slptime  = p->p_acct[LMS_SLEEP];
2798 2767                  pup->pr_wtime    = p->p_acct[LMS_WAIT_CPU];
2799 2768                  pup->pr_stoptime = p->p_acct[LMS_STOPPED];
2800 2769  
2801 2770                  pup->pr_minf  = p->p_ru.minflt;
2802 2771                  pup->pr_majf  = p->p_ru.majflt;
2803 2772                  pup->pr_nswap = p->p_ru.nswap;
2804 2773                  pup->pr_inblk = p->p_ru.inblock;
2805 2774                  pup->pr_oublk = p->p_ru.oublock;
2806 2775                  pup->pr_msnd  = p->p_ru.msgsnd;
2807 2776                  pup->pr_mrcv  = p->p_ru.msgrcv;
2808 2777                  pup->pr_sigs  = p->p_ru.nsignals;
2809 2778                  pup->pr_vctx  = p->p_ru.nvcsw;
2810 2779                  pup->pr_ictx  = p->p_ru.nivcsw;
2811 2780                  pup->pr_sysc  = p->p_ru.sysc;
2812 2781                  pup->pr_ioch  = p->p_ru.ioch;
2813 2782  
2814 2783                  prcvtusage32(pup, upup);
2815 2784  
2816 2785                  /*
2817 2786                   * Fill one prusage struct for each active lwp.
2818 2787                   */
2819 2788                  if ((t = p->p_tlist) != NULL &&
2820 2789                      !(pcp->prc_flags & PRC_DESTROY)) {
2821 2790                          do {
2822 2791                                  ASSERT(!(t->t_proc_flag & TP_LWPEXIT));
2823 2792                                  ASSERT(nlwp > 0);
2824 2793                                  --nlwp;
2825 2794                                  upup++;
2826 2795                                  prgetusage(t, pup);
2827 2796                                  prcvtusage32(pup, upup);
2828 2797                          } while ((t = t->t_forw) != p->p_tlist);
2829 2798                  }
2830 2799                  ASSERT(nlwp == 0);
2831 2800  
2832 2801                  prunlock(pnp);
2833 2802                  if (copyout(Bupup, cmaddr, (Nlwp+1) * sizeof (prusage32_t)))
2834 2803                          error = EFAULT;
2835 2804                  kmem_free(thing, thingsize);
2836 2805                  thing = NULL;
2837 2806                  break;
2838 2807          }
2839 2808  
2840 2809          case PIOCNAUXV:         /* get number of aux vector entries */
2841 2810          {
2842 2811                  int n = __KERN_NAUXV_IMPL;
2843 2812  
2844 2813                  prunlock(pnp);
2845 2814                  if (copyout(&n, cmaddr, sizeof (int)))
2846 2815                          error = EFAULT;
2847 2816                  break;
2848 2817          }
2849 2818  
2850 2819          case PIOCAUXV:          /* get aux vector (see sys/auxv.h) */
2851 2820          {
2852 2821                  int i;
2853 2822  
2854 2823                  if (PROCESS_NOT_32BIT(p)) {
2855 2824                          prunlock(pnp);
2856 2825                          error = EOVERFLOW;
2857 2826                  } else {
2858 2827                          up = PTOU(p);
2859 2828                          for (i = 0; i < __KERN_NAUXV_IMPL; i++) {
2860 2829                                  un32.auxv[i].a_type = up->u_auxv[i].a_type;
2861 2830                                  un32.auxv[i].a_un.a_val =
2862 2831                                      (int32_t)up->u_auxv[i].a_un.a_val;
2863 2832                          }
2864 2833                          prunlock(pnp);
2865 2834                          if (copyout(un32.auxv, cmaddr,
2866 2835                              __KERN_NAUXV_IMPL * sizeof (auxv32_t)))
2867 2836                                  error = EFAULT;
2868 2837                  }
2869 2838                  break;
2870 2839          }
2871 2840  
2872 2841  #if defined(__i386_COMPAT)
2873 2842          case PIOCNLDT:          /* get number of LDT entries */
2874 2843          {
2875 2844                  int n;
2876 2845  
2877 2846                  mutex_exit(&p->p_lock);
2878 2847                  mutex_enter(&p->p_ldtlock);
2879 2848                  n = prnldt(p);
2880 2849                  mutex_exit(&p->p_ldtlock);
2881 2850                  mutex_enter(&p->p_lock);
2882 2851                  prunlock(pnp);
2883 2852                  if (copyout(&n, cmaddr, sizeof (n)))
2884 2853                          error = EFAULT;
2885 2854                  break;
2886 2855          }
2887 2856  
2888 2857          case PIOCLDT:           /* get LDT entries */
2889 2858          {
2890 2859                  struct ssd *ssd;
2891 2860                  int n;
2892 2861  
2893 2862                  mutex_exit(&p->p_lock);
2894 2863                  mutex_enter(&p->p_ldtlock);
2895 2864                  n = prnldt(p);
2896 2865  
2897 2866                  if (thing && thingsize != (n+1) * sizeof (*ssd)) {
2898 2867                          kmem_free(thing, thingsize);
2899 2868                          thing = NULL;
2900 2869                  }
2901 2870                  if (thing == NULL) {
2902 2871                          thingsize = (n+1) * sizeof (*ssd);
2903 2872                          thing = kmem_alloc(thingsize, KM_NOSLEEP);
2904 2873                  }
2905 2874                  if (thing == NULL) {
2906 2875                          mutex_exit(&p->p_ldtlock);
2907 2876                          mutex_enter(&p->p_lock);
2908 2877                          prunlock(pnp);
2909 2878                          goto startover;
2910 2879                  }
2911 2880  
2912 2881                  ssd = thing;
2913 2882                  thing = NULL;
2914 2883                  if (n != 0)
2915 2884                          prgetldt(p, ssd);
2916 2885                  mutex_exit(&p->p_ldtlock);
2917 2886                  mutex_enter(&p->p_lock);
2918 2887                  prunlock(pnp);
2919 2888  
2920 2889                  /* mark the end of the list with a null entry */
2921 2890                  bzero(&ssd[n], sizeof (*ssd));
2922 2891                  if (copyout(ssd, cmaddr, (n+1) * sizeof (*ssd)))
2923 2892                          error = EFAULT;
2924 2893                  kmem_free(ssd, (n+1) * sizeof (*ssd));
2925 2894                  break;
2926 2895          }
2927 2896  #endif  /* __i386_COMPAT */
2928 2897  
2929 2898  #if defined(__sparc)
2930 2899          case PIOCGWIN:          /* get gwindows_t (see sys/reg.h) */
2931 2900          {
2932 2901                  gwindows32_t *gwp = thing;
2933 2902  
2934 2903                  if (PROCESS_NOT_32BIT(p)) {
2935 2904                          prunlock(pnp);
2936 2905                          error = EOVERFLOW;
2937 2906                  } else {
2938 2907                          /* drop p->p_lock while touching the stack */
2939 2908                          mutex_exit(&p->p_lock);
2940 2909                          bzero(gwp, sizeof (*gwp));
2941 2910                          prgetwindows32(lwp, gwp);
2942 2911                          mutex_enter(&p->p_lock);
2943 2912                          prunlock(pnp);
2944 2913                          if (copyout(gwp, cmaddr, sizeof (*gwp)))
2945 2914                                  error = EFAULT;
2946 2915                  }
2947 2916                  kmem_free(gwp, sizeof (*gwp));
2948 2917                  thing = NULL;
2949 2918                  break;
2950 2919          }
2951 2920  #endif  /* __sparc */
2952 2921  
2953 2922          default:
2954 2923                  prunlock(pnp);
2955 2924                  error = EINVAL;
2956 2925                  break;
2957 2926  
2958 2927          }
2959 2928  
2960 2929          ASSERT(thing == NULL);
2961 2930          ASSERT(xpnp == NULL);
2962 2931          return (error);
2963 2932  }
2964 2933  #endif  /* _SYSCALL32_IMPL */
2965 2934  
2966 2935  /*
2967 2936   * Distinguish "writeable" ioctl requests from others.
2968 2937   */
2969 2938  static int
2970 2939  isprwrioctl(int cmd)
2971 2940  {
2972 2941          switch (cmd) {
2973 2942          case PIOCSTOP:
2974 2943          case PIOCRUN:
2975 2944          case PIOCSTRACE:
2976 2945          case PIOCSSIG:
2977 2946          case PIOCKILL:
2978 2947          case PIOCUNKILL:
2979 2948          case PIOCNICE:
2980 2949          case PIOCSENTRY:
2981 2950          case PIOCSEXIT:
2982 2951          case PIOCSRLC:
2983 2952          case PIOCRRLC:
2984 2953          case PIOCSREG:
2985 2954          case PIOCSFPREG:
2986 2955          case PIOCSXREG:
2987 2956          case PIOCSHOLD:
2988 2957          case PIOCSFAULT:
2989 2958          case PIOCCFAULT:
2990 2959          case PIOCSFORK:
2991 2960          case PIOCRFORK:
2992 2961          case PIOCSET:
2993 2962          case PIOCRESET:
2994 2963                  return (1);
2995 2964          }
2996 2965          return (0);
2997 2966  }
2998 2967  
2999 2968  /*
3000 2969   * Map the ioctl() interface run flags to the new interface run flags.
3001 2970   */
3002 2971  static ulong_t
3003 2972  prmaprunflags(long flags)
3004 2973  {
3005 2974          ulong_t newflags = 0;
3006 2975  
3007 2976          if (flags & PRCSIG)
3008 2977                  newflags |= 0x01;
3009 2978          if (flags & PRCFAULT)
3010 2979                  newflags |= 0x02;
3011 2980          if (flags & PRSTEP)
3012 2981                  newflags |= 0x04;
3013 2982          if (flags & PRSABORT)
3014 2983                  newflags |= 0x08;
3015 2984          if (flags & PRSTOP)
3016 2985                  newflags |= 0x10;
3017 2986          return (newflags);
3018 2987  }
3019 2988  
3020 2989  /*
3021 2990   * Map the ioctl() interface settable mode flags to the new interface flags.
3022 2991   */
3023 2992  static long
3024 2993  prmapsetflags(long flags)
3025 2994  {
3026 2995          long newflags = 0;
3027 2996  
3028 2997  #define ALLFLAGS        \
3029 2998          (PR_FORK|PR_RLC|PR_KLC|PR_ASYNC|PR_BPTADJ|PR_MSACCT|PR_PCOMPAT)
3030 2999  
3031 3000          if (flags & ~ALLFLAGS)
3032 3001                  newflags = 0xffff;      /* forces EINVAL */
3033 3002          if (flags & PR_FORK)
3034 3003                  newflags |= (0x00100000 | 0x08000000);
3035 3004          if (flags & PR_RLC)
3036 3005                  newflags |= 0x00200000;
3037 3006          if (flags & PR_KLC)
3038 3007                  newflags |= 0x00400000;
3039 3008          if (flags & PR_ASYNC)
3040 3009                  newflags |= 0x00800000;
3041 3010          if (flags & PR_MSACCT)
3042 3011                  newflags |= 0x01000000;
3043 3012          if (flags & PR_BPTADJ)
3044 3013                  newflags |= 0x02000000;
3045 3014          if (flags & PR_PCOMPAT)
3046 3015                  newflags |= 0x04000000;
3047 3016          return (newflags);
3048 3017  }
3049 3018  
3050 3019  /*
3051 3020   * Apply PIOCRUN options specific to the ioctl() interface.
3052 3021   */
3053 3022  static void
3054 3023  prsetrun(kthread_t *t, prrun_t *prp)
3055 3024  {
3056 3025          proc_t *p = ttoproc(t);
3057 3026          klwp_t *lwp = ttolwp(t);
3058 3027          long flags = prp->pr_flags;
3059 3028          user_t *up = PTOU(p);
3060 3029  
3061 3030          ASSERT(MUTEX_HELD(&p->p_lock));
3062 3031  
3063 3032          if (flags & PRSHOLD) {
3064 3033                  schedctl_finish_sigblock(t);
3065 3034                  sigutok(&prp->pr_sighold, &t->t_hold);
3066 3035                  t->t_sig_check = 1;     /* so ISSIG will be done */
3067 3036          }
3068 3037          if (flags & PRSTRACE) {
3069 3038                  prdelset(&prp->pr_trace, SIGKILL);
3070 3039                  prassignset(&p->p_sigmask, &prp->pr_trace);
3071 3040                  if (!sigisempty(&p->p_sigmask))
3072 3041                          p->p_proc_flag |= P_PR_TRACE;
3073 3042                  else if (prisempty(&p->p_fltmask)) {
3074 3043                          if (up->u_systrap == 0)
3075 3044                                  p->p_proc_flag &= ~P_PR_TRACE;
3076 3045                  }
3077 3046          }
3078 3047          if (flags & PRSFAULT) {
3079 3048                  prassignset(&p->p_fltmask, &prp->pr_fault);
3080 3049                  if (!prisempty(&p->p_fltmask))
3081 3050                          p->p_proc_flag |= P_PR_TRACE;
3082 3051                  else if (sigisempty(&p->p_sigmask)) {
3083 3052                          if (up->u_systrap == 0)
3084 3053                                  p->p_proc_flag &= ~P_PR_TRACE;
3085 3054                  }
3086 3055          }
3087 3056          /*
3088 3057           * prsvaddr() must be called before prstep() because
3089 3058           * stepping can depend on the current value of the PC.
3090 3059           * We drop p_lock while touching the lwp's registers (on stack).
3091 3060           */
3092 3061          if (flags & PRSVADDR) {
3093 3062                  mutex_exit(&p->p_lock);
3094 3063                  prsvaddr(lwp, prp->pr_vaddr);
3095 3064                  mutex_enter(&p->p_lock);
3096 3065          }
3097 3066  }
3098 3067  
3099 3068  /*
3100 3069   * Common code for PIOCOPENM
3101 3070   * Returns with the process unlocked.
3102 3071   */
3103 3072  static int
3104 3073  propenm(prnode_t *pnp, caddr_t cmaddr, caddr_t va, int *rvalp, cred_t *cr)
3105 3074  {
3106 3075          proc_t *p = pnp->pr_common->prc_proc;
3107 3076          struct as *as = p->p_as;
3108 3077          int error = 0;
3109 3078          struct seg *seg;
3110 3079          struct vnode *xvp;
3111 3080          int n;
3112 3081  
3113 3082          /*
3114 3083           * By fiat, a system process has no address space.
3115 3084           */
3116 3085          if ((p->p_flag & SSYS) || as == &kas) {
3117 3086                  error = EINVAL;
3118 3087          } else if (cmaddr) {
3119 3088                  /*
3120 3089                   * We drop p_lock before grabbing the address
3121 3090                   * space lock in order to avoid a deadlock with
3122 3091                   * the clock thread.  The process will not
3123 3092                   * disappear and its address space will not
3124 3093                   * change because it is marked P_PR_LOCK.
3125 3094                   */
3126 3095                  mutex_exit(&p->p_lock);
3127 3096                  AS_LOCK_ENTER(as, RW_READER);
3128 3097                  seg = as_segat(as, va);
3129 3098                  if (seg != NULL &&
3130 3099                      seg->s_ops == &segvn_ops &&
3131 3100                      SEGOP_GETVP(seg, va, &xvp) == 0 &&
3132 3101                      xvp != NULL &&
3133 3102                      xvp->v_type == VREG) {
3134 3103                          VN_HOLD(xvp);
3135 3104                  } else {
3136 3105                          error = EINVAL;
3137 3106                  }
3138 3107                  AS_LOCK_EXIT(as);
3139 3108                  mutex_enter(&p->p_lock);
3140 3109          } else if ((xvp = p->p_exec) == NULL) {
3141 3110                  error = EINVAL;
3142 3111          } else {
3143 3112                  VN_HOLD(xvp);
3144 3113          }
3145 3114  
3146 3115          prunlock(pnp);
3147 3116  
3148 3117          if (error == 0) {
3149 3118                  if ((error = VOP_ACCESS(xvp, VREAD, 0, cr, NULL)) == 0)
3150 3119                          error = fassign(&xvp, FREAD, &n);
3151 3120                  if (error) {
3152 3121                          VN_RELE(xvp);
3153 3122                  } else {
3154 3123                          *rvalp = n;
3155 3124                  }
3156 3125          }
3157 3126  
3158 3127          return (error);
3159 3128  }
3160 3129  
3161 3130  /*
3162 3131   * Return old version of process/lwp status.
3163 3132   * The u-block is mapped in by this routine and unmapped at the end.
3164 3133   */
3165 3134  void
3166 3135  oprgetstatus(kthread_t *t, prstatus_t *sp, zone_t *zp)
3167 3136  {
3168 3137          proc_t *p = ttoproc(t);
3169 3138          klwp_t *lwp = ttolwp(t);
3170 3139          int flags;
3171 3140          user_t *up;
3172 3141          ulong_t instr;
3173 3142  
3174 3143          ASSERT(MUTEX_HELD(&p->p_lock));
3175 3144  
3176 3145          up = PTOU(p);
3177 3146          bzero(sp, sizeof (*sp));
3178 3147          flags = 0;
3179 3148          if (t->t_state == TS_STOPPED) {
3180 3149                  flags |= PR_STOPPED;
3181 3150                  if ((t->t_schedflag & TS_PSTART) == 0)
3182 3151                          flags |= PR_ISTOP;
3183 3152          } else if (VSTOPPED(t)) {
3184 3153                  flags |= PR_STOPPED|PR_ISTOP;
3185 3154          }
3186 3155          if (!(flags & PR_ISTOP) && (t->t_proc_flag & TP_PRSTOP))
3187 3156                  flags |= PR_DSTOP;
3188 3157          if (lwp->lwp_asleep)
3189 3158                  flags |= PR_ASLEEP;
3190 3159          if (p->p_proc_flag & P_PR_FORK)
3191 3160                  flags |= PR_FORK;
3192 3161          if (p->p_proc_flag & P_PR_RUNLCL)
3193 3162                  flags |= PR_RLC;
3194 3163          if (p->p_proc_flag & P_PR_KILLCL)
3195 3164                  flags |= PR_KLC;
3196 3165          if (p->p_proc_flag & P_PR_ASYNC)
3197 3166                  flags |= PR_ASYNC;
3198 3167          if (p->p_proc_flag & P_PR_BPTADJ)
3199 3168                  flags |= PR_BPTADJ;
3200 3169          if (p->p_proc_flag & P_PR_PTRACE)
3201 3170                  flags |= PR_PCOMPAT;
3202 3171          if (t->t_proc_flag & TP_MSACCT)
3203 3172                  flags |= PR_MSACCT;
3204 3173          sp->pr_flags = flags;
3205 3174          if (VSTOPPED(t)) {
3206 3175                  sp->pr_why   = PR_REQUESTED;
3207 3176                  sp->pr_what  = 0;
3208 3177          } else {
3209 3178                  sp->pr_why   = t->t_whystop;
3210 3179                  sp->pr_what  = t->t_whatstop;
3211 3180          }
3212 3181  
3213 3182          if (t->t_whystop == PR_FAULTED)
3214 3183                  bcopy(&lwp->lwp_siginfo,
3215 3184                      &sp->pr_info, sizeof (k_siginfo_t));
3216 3185          else if (lwp->lwp_curinfo)
3217 3186                  bcopy(&lwp->lwp_curinfo->sq_info,
3218 3187                      &sp->pr_info, sizeof (k_siginfo_t));
3219 3188  
3220 3189          if (SI_FROMUSER(&lwp->lwp_siginfo) && zp->zone_id != GLOBAL_ZONEID &&
3221 3190              sp->pr_info.si_zoneid != zp->zone_id) {
3222 3191                  sp->pr_info.si_pid = zp->zone_zsched->p_pid;
3223 3192                  sp->pr_info.si_uid = 0;
3224 3193                  sp->pr_info.si_ctid = -1;
3225 3194                  sp->pr_info.si_zoneid = zp->zone_id;
3226 3195          }
3227 3196  
3228 3197          sp->pr_cursig  = lwp->lwp_cursig;
3229 3198          prassignset(&sp->pr_sigpend, &p->p_sig);
3230 3199          prassignset(&sp->pr_lwppend, &t->t_sig);
3231 3200          prgethold(t, &sp->pr_sighold);
3232 3201          sp->pr_altstack = lwp->lwp_sigaltstack;
3233 3202          prgetaction(p, up, lwp->lwp_cursig, &sp->pr_action);
3234 3203          sp->pr_pid   = p->p_pid;
3235 3204          if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
3236 3205              (p->p_flag & SZONETOP)) {
3237 3206                  ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
3238 3207                  /*
3239 3208                   * Inside local zones, fake zsched's pid as parent pids for
3240 3209                   * processes which reference processes outside of the zone.
3241 3210                   */
3242 3211                  sp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
3243 3212          } else {
3244 3213                  sp->pr_ppid = p->p_ppid;
3245 3214          }
3246 3215          sp->pr_pgrp  = p->p_pgrp;
3247 3216          sp->pr_sid   = p->p_sessp->s_sid;
3248 3217          hrt2ts(mstate_aggr_state(p, LMS_USER), &sp->pr_utime);
3249 3218          hrt2ts(mstate_aggr_state(p, LMS_SYSTEM), &sp->pr_stime);
3250 3219          TICK_TO_TIMESTRUC(p->p_cutime, &sp->pr_cutime);
3251 3220          TICK_TO_TIMESTRUC(p->p_cstime, &sp->pr_cstime);
3252 3221          (void) strncpy(sp->pr_clname, sclass[t->t_cid].cl_name,
3253 3222              sizeof (sp->pr_clname) - 1);
3254 3223          sp->pr_who = t->t_tid;
3255 3224          sp->pr_nlwp = p->p_lwpcnt;
3256 3225          sp->pr_brkbase = p->p_brkbase;
3257 3226          sp->pr_brksize = p->p_brksize;
3258 3227          sp->pr_stkbase = prgetstackbase(p);
3259 3228          sp->pr_stksize = p->p_stksize;
3260 3229          sp->pr_oldcontext = (struct ucontext *)lwp->lwp_oldcontext;
3261 3230          sp->pr_processor = t->t_cpu->cpu_id;
3262 3231          sp->pr_bind = t->t_bind_cpu;
3263 3232  
3264 3233          /*
3265 3234           * Fetch the current instruction, if not a system process.
3266 3235           * We don't attempt this unless the lwp is stopped.
3267 3236           */
3268 3237          if ((p->p_flag & SSYS) || p->p_as == &kas)
3269 3238                  sp->pr_flags |= (PR_ISSYS|PR_PCINVAL);
3270 3239          else if (!(flags & PR_STOPPED))
3271 3240                  sp->pr_flags |= PR_PCINVAL;
3272 3241          else if (!prfetchinstr(lwp, &instr))
3273 3242                  sp->pr_flags |= PR_PCINVAL;
3274 3243          else
3275 3244                  sp->pr_instr = instr;
3276 3245  
3277 3246          /*
3278 3247           * Drop p_lock while touching the lwp's stack.
3279 3248           */
3280 3249          mutex_exit(&p->p_lock);
3281 3250          if (prisstep(lwp))
3282 3251                  sp->pr_flags |= PR_STEP;
3283 3252          if ((flags & (PR_STOPPED|PR_ASLEEP)) && t->t_sysnum) {
3284 3253                  int i;
3285 3254                  auxv_t *auxp;
3286 3255  
3287 3256                  sp->pr_syscall = get_syscall_args(lwp,
3288 3257                      (long *)sp->pr_sysarg, &i);
3289 3258                  sp->pr_nsysarg = (short)i;
3290 3259                  if (t->t_whystop == PR_SYSEXIT && t->t_sysnum == SYS_execve) {
3291 3260                          sp->pr_sysarg[0] = 0;
3292 3261                          sp->pr_sysarg[1] = (uintptr_t)up->u_argv;
3293 3262                          sp->pr_sysarg[2] = (uintptr_t)up->u_envp;
3294 3263                          for (i = 0, auxp = up->u_auxv;
3295 3264                              i < sizeof (up->u_auxv) / sizeof (up->u_auxv[0]);
3296 3265                              i++, auxp++) {
3297 3266                                  if (auxp->a_type == AT_SUN_EXECNAME) {
3298 3267                                          sp->pr_sysarg[0] =
3299 3268                                              (uintptr_t)auxp->a_un.a_ptr;
3300 3269                                          break;
3301 3270                                  }
3302 3271                          }
3303 3272                  }
3304 3273          }
3305 3274          if ((flags & PR_STOPPED) || t == curthread)
3306 3275                  prgetprregs(lwp, sp->pr_reg);
3307 3276          mutex_enter(&p->p_lock);
3308 3277  }
3309 3278  
3310 3279  /*
3311 3280   * Return old version of information used by ps(1).
3312 3281   */
3313 3282  void
3314 3283  oprgetpsinfo(proc_t *p, prpsinfo_t *psp, kthread_t *tp)
3315 3284  {
3316 3285          kthread_t *t;
3317 3286          char c, state;
3318 3287          user_t *up;
3319 3288          dev_t d;
3320 3289          uint64_t pct;
3321 3290          int retval, niceval;
3322 3291          cred_t *cred;
3323 3292          struct as *as;
3324 3293          hrtime_t hrutime, hrstime, cur_time;
3325 3294  
3326 3295          ASSERT(MUTEX_HELD(&p->p_lock));
3327 3296  
3328 3297          bzero(psp, sizeof (*psp));
3329 3298  
3330 3299          if ((t = tp) == NULL)
3331 3300                  t = prchoose(p);        /* returns locked thread */
3332 3301          else
3333 3302                  thread_lock(t);
3334 3303  
3335 3304          /* kludge: map thread state enum into process state enum */
3336 3305  
3337 3306          if (t == NULL) {
3338 3307                  state = TS_ZOMB;
3339 3308          } else {
3340 3309                  state = VSTOPPED(t) ? TS_STOPPED : t->t_state;
3341 3310                  thread_unlock(t);
3342 3311          }
3343 3312  
3344 3313          switch (state) {
3345 3314          case TS_SLEEP:          state = SSLEEP;         break;
3346 3315          case TS_RUN:            state = SRUN;           break;
3347 3316          case TS_ONPROC:         state = SONPROC;        break;
3348 3317          case TS_ZOMB:           state = SZOMB;          break;
3349 3318          case TS_STOPPED:        state = SSTOP;          break;
3350 3319          default:                state = 0;              break;
3351 3320          }
3352 3321          switch (state) {
3353 3322          case SSLEEP:    c = 'S';        break;
3354 3323          case SRUN:      c = 'R';        break;
3355 3324          case SZOMB:     c = 'Z';        break;
3356 3325          case SSTOP:     c = 'T';        break;
3357 3326          case SIDL:      c = 'I';        break;
3358 3327          case SONPROC:   c = 'O';        break;
3359 3328  #ifdef SXBRK
3360 3329          case SXBRK:     c = 'X';        break;
3361 3330  #endif
3362 3331          default:        c = '?';        break;
3363 3332          }
3364 3333          psp->pr_state = state;
3365 3334          psp->pr_sname = c;
3366 3335          psp->pr_zomb = (state == SZOMB);
3367 3336          /*
3368 3337           * only export SSYS and SMSACCT; everything else is off-limits to
3369 3338           * userland apps.
3370 3339           */
3371 3340          psp->pr_flag = p->p_flag & (SSYS | SMSACCT);
3372 3341  
3373 3342          mutex_enter(&p->p_crlock);
3374 3343          cred = p->p_cred;
3375 3344          psp->pr_uid = crgetruid(cred);
3376 3345          psp->pr_gid = crgetrgid(cred);
3377 3346          psp->pr_euid = crgetuid(cred);
3378 3347          psp->pr_egid = crgetgid(cred);
3379 3348          mutex_exit(&p->p_crlock);
3380 3349  
3381 3350          psp->pr_pid = p->p_pid;
3382 3351          if (curproc->p_zone->zone_id != GLOBAL_ZONEID &&
3383 3352              (p->p_flag & SZONETOP)) {
3384 3353                  ASSERT(p->p_zone->zone_id != GLOBAL_ZONEID);
3385 3354                  /*
3386 3355                   * Inside local zones, fake zsched's pid as parent pids for
3387 3356                   * processes which reference processes outside of the zone.
3388 3357                   */
3389 3358                  psp->pr_ppid = curproc->p_zone->zone_zsched->p_pid;
3390 3359          } else {
3391 3360                  psp->pr_ppid = p->p_ppid;
3392 3361          }
3393 3362          psp->pr_pgrp = p->p_pgrp;
3394 3363          psp->pr_sid = p->p_sessp->s_sid;
3395 3364          psp->pr_addr = prgetpsaddr(p);
3396 3365          hrutime = mstate_aggr_state(p, LMS_USER);
3397 3366          hrstime = mstate_aggr_state(p, LMS_SYSTEM);
3398 3367          hrt2ts(hrutime + hrstime, &psp->pr_time);
3399 3368          TICK_TO_TIMESTRUC(p->p_cutime + p->p_cstime, &psp->pr_ctime);
3400 3369          switch (p->p_model) {
3401 3370          case DATAMODEL_ILP32:
3402 3371                  psp->pr_dmodel = PR_MODEL_ILP32;
3403 3372                  break;
3404 3373          case DATAMODEL_LP64:
3405 3374                  psp->pr_dmodel = PR_MODEL_LP64;
3406 3375                  break;
3407 3376          }
3408 3377          if (state == SZOMB || t == NULL) {
3409 3378                  int wcode = p->p_wcode;         /* must be atomic read */
3410 3379  
3411 3380                  if (wcode)
3412 3381                          psp->pr_wstat = wstat(wcode, p->p_wdata);
3413 3382                  psp->pr_lttydev = PRNODEV;
3414 3383                  psp->pr_ottydev = (o_dev_t)PRNODEV;
3415 3384                  psp->pr_size = 0;
3416 3385                  psp->pr_rssize = 0;
3417 3386                  psp->pr_pctmem = 0;
3418 3387          } else {
3419 3388                  up = PTOU(p);
3420 3389                  psp->pr_wchan = t->t_wchan;
3421 3390                  psp->pr_pri = t->t_pri;
3422 3391                  (void) strncpy(psp->pr_clname, sclass[t->t_cid].cl_name,
3423 3392                      sizeof (psp->pr_clname) - 1);
3424 3393                  retval = CL_DONICE(t, NULL, 0, &niceval);
3425 3394                  if (retval == 0) {
3426 3395                          psp->pr_oldpri = v.v_maxsyspri - psp->pr_pri;
3427 3396                          psp->pr_nice = niceval + NZERO;
3428 3397                  } else {
3429 3398                          psp->pr_oldpri = 0;
3430 3399                          psp->pr_nice = 0;
3431 3400                  }
3432 3401                  d = cttydev(p);
3433 3402  #ifdef sun
3434 3403                  {
3435 3404                          extern dev_t rwsconsdev, rconsdev, uconsdev;
3436 3405                          /*
3437 3406                           * If the controlling terminal is the real
3438 3407                           * or workstation console device, map to what the
3439 3408                           * user thinks is the console device. Handle case when
3440 3409                           * rwsconsdev or rconsdev is set to NODEV for Starfire.
3441 3410                           */
3442 3411                          if ((d == rwsconsdev || d == rconsdev) && d != NODEV)
3443 3412                                  d = uconsdev;
3444 3413                  }
3445 3414  #endif
3446 3415                  psp->pr_lttydev = (d == NODEV) ? PRNODEV : d;
3447 3416                  psp->pr_ottydev = cmpdev(d);
3448 3417                  psp->pr_start = up->u_start;
3449 3418                  bcopy(up->u_comm, psp->pr_fname,
3450 3419                      MIN(sizeof (up->u_comm), sizeof (psp->pr_fname)-1));
3451 3420                  bcopy(up->u_psargs, psp->pr_psargs,
3452 3421                      MIN(PRARGSZ-1, PSARGSZ));
3453 3422                  psp->pr_syscall = t->t_sysnum;
3454 3423                  psp->pr_argc = up->u_argc;
3455 3424                  psp->pr_argv = (char **)up->u_argv;
3456 3425                  psp->pr_envp = (char **)up->u_envp;
3457 3426  
3458 3427                  /* compute %cpu for the lwp or process */
3459 3428                  pct = 0;
3460 3429                  if ((t = tp) == NULL)
3461 3430                          t = p->p_tlist;
3462 3431                  cur_time = gethrtime_unscaled();
3463 3432                  do {
3464 3433                          pct += cpu_update_pct(t, cur_time);
3465 3434                          if (tp != NULL)         /* just do the one lwp */
3466 3435                                  break;
3467 3436                  } while ((t = t->t_forw) != p->p_tlist);
3468 3437  
3469 3438                  psp->pr_pctcpu = prgetpctcpu(pct);
3470 3439                  psp->pr_cpu = (psp->pr_pctcpu*100 + 0x6000) >> 15; /* [0..99] */
3471 3440                  if (psp->pr_cpu > 99)
3472 3441                          psp->pr_cpu = 99;
3473 3442  
3474 3443                  if ((p->p_flag & SSYS) || (as = p->p_as) == &kas) {
3475 3444                          psp->pr_size = 0;
3476 3445                          psp->pr_rssize = 0;
3477 3446                          psp->pr_pctmem = 0;
3478 3447                  } else {
3479 3448                          mutex_exit(&p->p_lock);
3480 3449                          AS_LOCK_ENTER(as, RW_READER);
3481 3450                          psp->pr_size = btopr(as->a_resvsize);
3482 3451                          psp->pr_rssize = rm_asrss(as);
3483 3452                          psp->pr_pctmem = rm_pctmemory(as);
3484 3453                          AS_LOCK_EXIT(as);
3485 3454                          mutex_enter(&p->p_lock);
3486 3455                  }
3487 3456          }
3488 3457          psp->pr_bysize = ptob(psp->pr_size);
3489 3458          psp->pr_byrssize = ptob(psp->pr_rssize);
3490 3459  }
3491 3460  
3492 3461  /*
3493 3462   * Return an array of structures with memory map information.
3494 3463   * We allocate here; the caller must deallocate.
3495 3464   * The caller is also responsible to append the zero-filled entry
3496 3465   * that terminates the PIOCMAP output buffer.
3497 3466   */
3498 3467  static int
3499 3468  oprgetmap(proc_t *p, list_t *iolhead)
3500 3469  {
3501 3470          struct as *as = p->p_as;
3502 3471          prmap_t *mp;
3503 3472          struct seg *seg;
3504 3473          struct seg *brkseg, *stkseg;
3505 3474          uint_t prot;
3506 3475  
3507 3476          ASSERT(as != &kas && AS_WRITE_HELD(as));
3508 3477  
3509 3478          /*
3510 3479           * Request an initial buffer size that doesn't waste memory
3511 3480           * if the address space has only a small number of segments.
3512 3481           */
3513 3482          pr_iol_initlist(iolhead, sizeof (*mp), avl_numnodes(&as->a_segtree));
3514 3483  
3515 3484          if ((seg = AS_SEGFIRST(as)) == NULL)
3516 3485                  return (0);
3517 3486  
3518 3487          brkseg = break_seg(p);
3519 3488          stkseg = as_segat(as, prgetstackbase(p));
3520 3489  
3521 3490          do {
3522 3491                  caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
3523 3492                  caddr_t saddr, naddr;
3524 3493                  void *tmp = NULL;
3525 3494  
3526 3495                  if ((seg->s_flags & S_HOLE) != 0) {
3527 3496                          continue;
3528 3497                  }
3529 3498  
3530 3499                  for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
3531 3500                          prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
3532 3501                          if (saddr == naddr)
3533 3502                                  continue;
3534 3503  
3535 3504                          mp = pr_iol_newbuf(iolhead, sizeof (*mp));
3536 3505  
3537 3506                          mp->pr_vaddr = saddr;
3538 3507                          mp->pr_size = naddr - saddr;
3539 3508                          mp->pr_off = SEGOP_GETOFFSET(seg, saddr);
3540 3509                          mp->pr_mflags = 0;
3541 3510                          if (prot & PROT_READ)
3542 3511                                  mp->pr_mflags |= MA_READ;
3543 3512                          if (prot & PROT_WRITE)
3544 3513                                  mp->pr_mflags |= MA_WRITE;
3545 3514                          if (prot & PROT_EXEC)
3546 3515                                  mp->pr_mflags |= MA_EXEC;
3547 3516                          if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
3548 3517                                  mp->pr_mflags |= MA_SHARED;
3549 3518                          if (seg == brkseg)
3550 3519                                  mp->pr_mflags |= MA_BREAK;
3551 3520                          else if (seg == stkseg)
3552 3521                                  mp->pr_mflags |= MA_STACK;
3553 3522                          mp->pr_pagesize = PAGESIZE;
3554 3523                  }
3555 3524                  ASSERT(tmp == NULL);
3556 3525          } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3557 3526  
3558 3527          return (0);
3559 3528  }
3560 3529  
3561 3530  #ifdef _SYSCALL32_IMPL
3562 3531  static int
3563 3532  oprgetmap32(proc_t *p, list_t *iolhead)
3564 3533  {
3565 3534          struct as *as = p->p_as;
3566 3535          ioc_prmap32_t *mp;
3567 3536          struct seg *seg;
3568 3537          struct seg *brkseg, *stkseg;
3569 3538          uint_t prot;
3570 3539  
3571 3540          ASSERT(as != &kas && AS_WRITE_HELD(as));
3572 3541  
3573 3542          /*
3574 3543           * Request an initial buffer size that doesn't waste memory
3575 3544           * if the address space has only a small number of segments.
3576 3545           */
3577 3546          pr_iol_initlist(iolhead, sizeof (*mp), avl_numnodes(&as->a_segtree));
3578 3547  
3579 3548          if ((seg = AS_SEGFIRST(as)) == NULL)
3580 3549                  return (0);
3581 3550  
3582 3551          brkseg = break_seg(p);
3583 3552          stkseg = as_segat(as, prgetstackbase(p));
3584 3553  
3585 3554          do {
3586 3555                  caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
3587 3556                  caddr_t saddr, naddr;
3588 3557                  void *tmp = NULL;
3589 3558  
3590 3559                  if ((seg->s_flags & S_HOLE) != 0) {
3591 3560                          continue;
3592 3561                  }
3593 3562  
3594 3563                  for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
3595 3564                          prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
3596 3565                          if (saddr == naddr)
3597 3566                                  continue;
3598 3567  
3599 3568                          mp = pr_iol_newbuf(iolhead, sizeof (*mp));
3600 3569  
3601 3570                          mp->pr_vaddr = (caddr32_t)(uintptr_t)saddr;
3602 3571                          mp->pr_size = (size32_t)(naddr - saddr);
3603 3572                          mp->pr_off = (off32_t)SEGOP_GETOFFSET(seg, saddr);
3604 3573                          mp->pr_mflags = 0;
3605 3574                          if (prot & PROT_READ)
3606 3575                                  mp->pr_mflags |= MA_READ;
3607 3576                          if (prot & PROT_WRITE)
3608 3577                                  mp->pr_mflags |= MA_WRITE;
3609 3578                          if (prot & PROT_EXEC)
3610 3579                                  mp->pr_mflags |= MA_EXEC;
3611 3580                          if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
3612 3581                                  mp->pr_mflags |= MA_SHARED;
3613 3582                          if (seg == brkseg)
3614 3583                                  mp->pr_mflags |= MA_BREAK;
3615 3584                          else if (seg == stkseg)
3616 3585                                  mp->pr_mflags |= MA_STACK;
3617 3586                          mp->pr_pagesize = PAGESIZE;
3618 3587                  }
3619 3588                  ASSERT(tmp == NULL);
3620 3589          } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3621 3590  
3622 3591          return (0);
3623 3592  }
3624 3593  #endif  /* _SYSCALL32_IMPL */
3625 3594  
3626 3595  /*
3627 3596   * Return the size of the old /proc page data file.
3628 3597   */
3629 3598  size_t
3630 3599  oprpdsize(struct as *as)
3631 3600  {
3632 3601          struct seg *seg;
3633 3602          size_t size;
3634 3603  
3635 3604          ASSERT(as != &kas && AS_WRITE_HELD(as));
3636 3605  
3637 3606          if ((seg = AS_SEGFIRST(as)) == NULL)
3638 3607                  return (0);
3639 3608  
3640 3609          size = sizeof (prpageheader_t);
3641 3610          do {
3642 3611                  caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
3643 3612                  caddr_t saddr, naddr;
3644 3613                  void *tmp = NULL;
3645 3614                  size_t npage;
3646 3615  
3647 3616                  if ((seg->s_flags & S_HOLE) != 0) {
3648 3617                          continue;
3649 3618                  }
3650 3619  
3651 3620                  for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
3652 3621                          (void) pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
3653 3622                          if ((npage = (naddr - saddr) / PAGESIZE) != 0)
3654 3623                                  size += sizeof (prasmap_t) + roundlong(npage);
3655 3624                  }
3656 3625                  ASSERT(tmp == NULL);
3657 3626          } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3658 3627  
3659 3628          return (size);
3660 3629  }
3661 3630  
3662 3631  #ifdef _SYSCALL32_IMPL
3663 3632  size_t
3664 3633  oprpdsize32(struct as *as)
3665 3634  {
3666 3635          struct seg *seg;
3667 3636          size_t size;
3668 3637  
3669 3638          ASSERT(as != &kas && AS_WRITE_HELD(as));
3670 3639  
3671 3640          if ((seg = AS_SEGFIRST(as)) == NULL)
3672 3641                  return (0);
3673 3642  
3674 3643          size = sizeof (ioc_prpageheader32_t);
3675 3644          do {
3676 3645                  caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
3677 3646                  caddr_t saddr, naddr;
3678 3647                  void *tmp = NULL;
3679 3648                  size_t npage;
3680 3649  
3681 3650                  if ((seg->s_flags & S_HOLE) != 0) {
3682 3651                          continue;
3683 3652                  }
3684 3653  
3685 3654                  for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
3686 3655                          (void) pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
3687 3656                          if ((npage = (naddr - saddr) / PAGESIZE) != 0)
3688 3657                                  size += sizeof (ioc_prmap32_t) + round4(npage);
3689 3658                  }
3690 3659                  ASSERT(tmp == NULL);
3691 3660          } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3692 3661  
3693 3662          return (size);
3694 3663  }
3695 3664  #endif  /* _SYSCALL32_IMPL */
3696 3665  
3697 3666  /*
3698 3667   * Read old /proc page data information.
3699 3668   */
3700 3669  int
3701 3670  oprpdread(struct as *as, uint_t hatid, struct uio *uiop)
3702 3671  {
3703 3672          caddr_t buf;
3704 3673          size_t size;
3705 3674          prpageheader_t *php;
3706 3675          prasmap_t *pmp;
3707 3676          struct seg *seg;
3708 3677          int error;
3709 3678  
3710 3679  again:
3711 3680          AS_LOCK_ENTER(as, RW_WRITER);
3712 3681  
3713 3682          if ((seg = AS_SEGFIRST(as)) == NULL) {
3714 3683                  AS_LOCK_EXIT(as);
3715 3684                  return (0);
3716 3685          }
3717 3686          size = oprpdsize(as);
3718 3687          if (uiop->uio_resid < size) {
3719 3688                  AS_LOCK_EXIT(as);
3720 3689                  return (E2BIG);
3721 3690          }
3722 3691  
3723 3692          buf = kmem_zalloc(size, KM_SLEEP);
3724 3693          php = (prpageheader_t *)buf;
3725 3694          pmp = (prasmap_t *)(buf + sizeof (prpageheader_t));
3726 3695  
3727 3696          hrt2ts(gethrtime(), &php->pr_tstamp);
3728 3697          php->pr_nmap = 0;
3729 3698          php->pr_npage = 0;
3730 3699          do {
3731 3700                  caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
3732 3701                  caddr_t saddr, naddr;
3733 3702                  void *tmp = NULL;
3734 3703  
3735 3704                  if ((seg->s_flags & S_HOLE) != 0) {
3736 3705                          continue;
3737 3706                  }
3738 3707  
3739 3708                  for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
3740 3709                          size_t len;
3741 3710                          size_t npage;
3742 3711                          uint_t prot;
3743 3712                          uintptr_t next;
3744 3713  
3745 3714                          prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
3746 3715                          if ((len = naddr - saddr) == 0)
3747 3716                                  continue;
3748 3717                          npage = len / PAGESIZE;
3749 3718                          next = (uintptr_t)(pmp + 1) + roundlong(npage);
3750 3719                          /*
3751 3720                           * It's possible that the address space can change
3752 3721                           * subtlely even though we're holding as->a_lock
3753 3722                           * due to the nondeterminism of page_exists() in
3754 3723                           * the presence of asychronously flushed pages or
3755 3724                           * mapped files whose sizes are changing.
3756 3725                           * page_exists() may be called indirectly from
3757 3726                           * pr_getprot() by a SEGOP_INCORE() routine.
3758 3727                           * If this happens we need to make sure we don't
3759 3728                           * overrun the buffer whose size we computed based
3760 3729                           * on the initial iteration through the segments.
3761 3730                           * Once we've detected an overflow, we need to clean
3762 3731                           * up the temporary memory allocated in pr_getprot()
3763 3732                           * and retry. If there's a pending signal, we return
3764 3733                           * EINTR so that this thread can be dislodged if
3765 3734                           * a latent bug causes us to spin indefinitely.
3766 3735                           */
3767 3736                          if (next > (uintptr_t)buf + size) {
3768 3737                                  pr_getprot_done(&tmp);
3769 3738                                  AS_LOCK_EXIT(as);
3770 3739  
3771 3740                                  kmem_free(buf, size);
3772 3741  
3773 3742                                  if (ISSIG(curthread, JUSTLOOKING))
3774 3743                                          return (EINTR);
3775 3744  
3776 3745                                  goto again;
3777 3746                          }
3778 3747  
3779 3748                          php->pr_nmap++;
3780 3749                          php->pr_npage += npage;
3781 3750                          pmp->pr_vaddr = saddr;
3782 3751                          pmp->pr_npage = npage;
3783 3752                          pmp->pr_off = SEGOP_GETOFFSET(seg, saddr);
3784 3753                          pmp->pr_mflags = 0;
3785 3754                          if (prot & PROT_READ)
3786 3755                                  pmp->pr_mflags |= MA_READ;
3787 3756                          if (prot & PROT_WRITE)
3788 3757                                  pmp->pr_mflags |= MA_WRITE;
3789 3758                          if (prot & PROT_EXEC)
3790 3759                                  pmp->pr_mflags |= MA_EXEC;
3791 3760                          if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
3792 3761                                  pmp->pr_mflags |= MA_SHARED;
3793 3762                          pmp->pr_pagesize = PAGESIZE;
3794 3763                          hat_getstat(as, saddr, len, hatid,
3795 3764                              (char *)(pmp + 1), HAT_SYNC_ZERORM);
3796 3765                          pmp = (prasmap_t *)next;
3797 3766                  }
3798 3767                  ASSERT(tmp == NULL);
3799 3768          } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3800 3769  
3801 3770          AS_LOCK_EXIT(as);
3802 3771  
3803 3772          ASSERT((uintptr_t)pmp <= (uintptr_t)buf + size);
3804 3773          error = uiomove(buf, (caddr_t)pmp - buf, UIO_READ, uiop);
3805 3774          kmem_free(buf, size);
3806 3775  
3807 3776          return (error);
3808 3777  }
3809 3778  
3810 3779  #ifdef _SYSCALL32_IMPL
3811 3780  int
3812 3781  oprpdread32(struct as *as, uint_t hatid, struct uio *uiop)
3813 3782  {
3814 3783          caddr_t buf;
3815 3784          size_t size;
3816 3785          ioc_prpageheader32_t *php;
3817 3786          ioc_prasmap32_t *pmp;
3818 3787          struct seg *seg;
3819 3788          int error;
3820 3789  
3821 3790  again:
3822 3791          AS_LOCK_ENTER(as, RW_WRITER);
3823 3792  
3824 3793          if ((seg = AS_SEGFIRST(as)) == NULL) {
3825 3794                  AS_LOCK_EXIT(as);
3826 3795                  return (0);
3827 3796          }
3828 3797          size = oprpdsize32(as);
3829 3798          if (uiop->uio_resid < size) {
3830 3799                  AS_LOCK_EXIT(as);
3831 3800                  return (E2BIG);
3832 3801          }
3833 3802  
3834 3803          buf = kmem_zalloc(size, KM_SLEEP);
3835 3804          php = (ioc_prpageheader32_t *)buf;
3836 3805          pmp = (ioc_prasmap32_t *)(buf + sizeof (ioc_prpageheader32_t));
3837 3806  
3838 3807          hrt2ts32(gethrtime(), &php->pr_tstamp);
3839 3808          php->pr_nmap = 0;
3840 3809          php->pr_npage = 0;
3841 3810          do {
3842 3811                  caddr_t eaddr = seg->s_base + pr_getsegsize(seg, 0);
3843 3812                  caddr_t saddr, naddr;
3844 3813                  void *tmp = NULL;
3845 3814  
3846 3815                  if ((seg->s_flags & S_HOLE) != 0) {
3847 3816                          continue;
3848 3817                  }
3849 3818  
3850 3819                  for (saddr = seg->s_base; saddr < eaddr; saddr = naddr) {
3851 3820                          size_t len;
3852 3821                          size_t npage;
3853 3822                          uint_t prot;
3854 3823                          uintptr_t next;
3855 3824  
3856 3825                          prot = pr_getprot(seg, 0, &tmp, &saddr, &naddr, eaddr);
3857 3826                          if ((len = naddr - saddr) == 0)
3858 3827                                  continue;
3859 3828                          npage = len / PAGESIZE;
3860 3829                          next = (uintptr_t)(pmp + 1) + round4(npage);
3861 3830                          /*
3862 3831                           * It's possible that the address space can change
3863 3832                           * subtlely even though we're holding as->a_lock
3864 3833                           * due to the nondeterminism of page_exists() in
3865 3834                           * the presence of asychronously flushed pages or
3866 3835                           * mapped files whose sizes are changing.
3867 3836                           * page_exists() may be called indirectly from
3868 3837                           * pr_getprot() by a SEGOP_INCORE() routine.
3869 3838                           * If this happens we need to make sure we don't
3870 3839                           * overrun the buffer whose size we computed based
3871 3840                           * on the initial iteration through the segments.
3872 3841                           * Once we've detected an overflow, we need to clean
3873 3842                           * up the temporary memory allocated in pr_getprot()
3874 3843                           * and retry. If there's a pending signal, we return
3875 3844                           * EINTR so that this thread can be dislodged if
3876 3845                           * a latent bug causes us to spin indefinitely.
3877 3846                           */
3878 3847                          if (next > (uintptr_t)buf + size) {
3879 3848                                  pr_getprot_done(&tmp);
3880 3849                                  AS_LOCK_EXIT(as);
3881 3850  
3882 3851                                  kmem_free(buf, size);
3883 3852  
3884 3853                                  if (ISSIG(curthread, JUSTLOOKING))
3885 3854                                          return (EINTR);
3886 3855  
3887 3856                                  goto again;
3888 3857                          }
3889 3858  
3890 3859                          php->pr_nmap++;
3891 3860                          php->pr_npage += npage;
3892 3861                          pmp->pr_vaddr = (uint32_t)(uintptr_t)saddr;
3893 3862                          pmp->pr_npage = (uint32_t)npage;
3894 3863                          pmp->pr_off = (int32_t)SEGOP_GETOFFSET(seg, saddr);
3895 3864                          pmp->pr_mflags = 0;
3896 3865                          if (prot & PROT_READ)
3897 3866                                  pmp->pr_mflags |= MA_READ;
3898 3867                          if (prot & PROT_WRITE)
3899 3868                                  pmp->pr_mflags |= MA_WRITE;
3900 3869                          if (prot & PROT_EXEC)
3901 3870                                  pmp->pr_mflags |= MA_EXEC;
3902 3871                          if (SEGOP_GETTYPE(seg, saddr) & MAP_SHARED)
3903 3872                                  pmp->pr_mflags |= MA_SHARED;
3904 3873                          pmp->pr_pagesize = PAGESIZE;
3905 3874                          hat_getstat(as, saddr, len, hatid,
3906 3875                              (char *)(pmp + 1), HAT_SYNC_ZERORM);
3907 3876                          pmp = (ioc_prasmap32_t *)next;
3908 3877                  }
3909 3878                  ASSERT(tmp == NULL);
3910 3879          } while ((seg = AS_SEGNEXT(as, seg)) != NULL);
3911 3880  
3912 3881          AS_LOCK_EXIT(as);
3913 3882  
3914 3883          ASSERT((uintptr_t)pmp == (uintptr_t)buf + size);
3915 3884          error = uiomove(buf, (caddr_t)pmp - buf, UIO_READ, uiop);
3916 3885          kmem_free(buf, size);
3917 3886  
3918 3887          return (error);
3919 3888  }
3920 3889  #endif  /* _SYSCALL32_IMPL */
3921 3890  
3922 3891  /*ARGSUSED*/
3923 3892  #ifdef _SYSCALL32_IMPL
3924 3893  int
3925 3894  prioctl(
3926 3895          struct vnode *vp,
3927 3896          int cmd,
3928 3897          intptr_t arg,
3929 3898          int flag,
3930 3899          cred_t *cr,
3931 3900          int *rvalp,
3932 3901          caller_context_t *ct)
3933 3902  {
3934 3903          switch (curproc->p_model) {
3935 3904          case DATAMODEL_ILP32:
3936 3905                  return (prioctl32(vp, cmd, arg, flag, cr, rvalp, ct));
3937 3906          case DATAMODEL_LP64:
3938 3907                  return (prioctl64(vp, cmd, arg, flag, cr, rvalp, ct));
3939 3908          default:
3940 3909                  return (ENOSYS);
3941 3910          }
3942 3911  }
3943 3912  #endif  /* _SYSCALL32_IMPL */
  
    | 
      ↓ open down ↓ | 
    1493 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX