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