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