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