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