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