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