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