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