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