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