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